';
+ var tinp = ' '
+ + (s.serverOptions.mmode != 'onhold' ? '' : (
+ trth + $JCL("approveUser") + trtd + aumsg
+ + tinp + $JCL("approveUser") + cb('approveuser')))
+ + trth + $JCL("approveMessage")
+ + mtrt + ammsg
+ + tinp + $JCL("approveMessage") + cb('approve')
+ + trth + $JCL("deleteUnwantedComment")
+ + trtd + $JCL("getRidOfComment")
+ + tinp + $JCL("deleteMessage") + cb('delete')
+ + ((cmtreason == 'User' || cmtreason == 'IP') ?
+ '' :
+ trth + $JCL("flagAsSpam")
+ + trtd + $JCL("trainAksimet")
+ + tinp + $JCL("spamJunk") + cb('spam'))
+ + ((cmtreason == 'User') ?
+ unbantext
+ : trth + $JCL("blockCommenter")
+ + trtd + $JCL("hideCommentsFromUser")
+ + tinp + $JCL("blockUser")+cb('user'))
+ + ((cmtreason == 'IP') ?
+ unbantext
+ : trth + $JCL("blockCommenterIP")
+ + trtd + $JCL("hideCommentsFromIP")
+ + tinp + $JCL("blockIP")+cb('ip'))
+ + "");
+ }
+ s.settingsWindow('ctBlock', cmt.domCtls || cmt.domINFO, s.blockDom[status][cmtreason]);
+ s.ctBlock.forId = cid;
+}
+JSCC.prototype.cmtApprove = function(cid) {
+ var cmt = this.jspg.getItemById(cid).div;
+ if(cmt.cobj.status == 'S') {
+ this.cmtSetSpamStatus(cmt, false);
+ cmt.cobj.status = 'S'; // cmtDelete's deal
+ }
+ if(cmt.cobj.status == 'O') {
+ this.cmtSetOffensiveStatus(cmt, false);
+ cmt.cobj.status = 'O';
+ }
+ this.cmtDelete(cid, 'message');
+}
+
+JSCC.prototype.cmtApproveUser = function(cid) {
+ var cmt = this.jspg.getItemById(cid).div;
+ if(cmt.cobj.status == 'S') {
+ this.cmtSetSpamStatus(cmt, false);
+ cmt.cobj.status = 'S'; // cmtDelete's deal
+ }
+ this.cmtDelete(cid, 'user');
+}
+
+JSCC.prototype.routeAction = function(fun) {
+ var a = [this];
+ for(var i = 0; i < $JCA.length; i++) {
+ if($JCA[i].jcaIndex != this.jcaIndex
+ && $JCA[i].config.domain == this.config.domain
+ && $JCA[i].config.path == this.config.path
+ && $JCA[i].config['display-mode'] == 'inline'
+ && !this.IM && !$JCA[i].IM && !$JCA[i].config.userProfileComments)
+ a.push($JCA[i]);
+ }
+ for(var i = 0; i < a.length; i++) {
+ var e = a[i];
+ if(i) e.serverFilter = function(n) {
+ return (n == 's-data.js'); }
+ fun.apply(e);
+ delete e.serverFilter;
+ }
+}
+
+JSCC.prototype.cmtDelete = function(cid, approvalMode) {
+ var args = arguments;
+ this.routeAction(function() {
+ this.cmtDeleteAct.apply(this, args);
+ });
+}
+
+JSCC.prototype.cmtDeleteAct = function(cid, approvalMode, action) {
+ var s = this;
+ var item = this.jspg.getItemById(cid);
+ if (!item) return;
+ var cmt = item.div;
+ if(!cmt) {
+ (this.objById[cid]||{}).status = 'D';
+ this.jspg.deleteItem(cid);
+ this.reCalcPages();
+ return;
+ }
+
+ if(arguments.length == 1) approvalMode = 'delete';
+
+ var oldStatus = cmt.cobj.status;
+
+ var path = (this.config.moderate || (this.config.nolc && !this.IM)) ?
+ cmt.cobj.path : this.config.path;
+ if(this.config.nolc && !this.IM)
+ this.config.domain = cmt.cobj.domain;
+ this.moderationCommentsListUpdate(cid);
+ var idlist = [{'id': cid, 'p': path}];
+ switch(approvalMode) {
+ case 'message':
+ if (!this.inlineModeration) {
+ this.preHandlerDelete(cmt);
+ }
+ if(oldStatus == 'S') {
+ this.groupModerationRequest(approvalMode,
+ {'spam': idlist, 'appr': [], 'del': []});
+ cmt.cobj.action = 'unban';
+ } else if(oldStatus == 'O') {
+ this.groupModerationRequest(approvalMode,
+ {'spam': [], 'appr': idlist, 'del': []});
+ } else {
+ this.groupModerationRequest(approvalMode,
+ {'spam': [], 'appr': [], 'del': idlist});
+ }
+ if (this.inlineModeration) this.postHandlerModerate(cid);
+ break;
+ case 'user':
+ if (!this.inlineModeration) {
+ this.preHandlerDelete(cmt);
+ }
+ this.groupModerationRequest(approvalMode, idlist,
+ (oldStatus == 'S' ? {'junk': 'no'} : {}));
+ if (this.inlineModeration) this.postHandlerModerate(cid);
+ break;
+ case 'delete':
+ this.preHandlerDelete(cmt);
+ this.groupModerationRequest(approvalMode, idlist);
+ break;
+ case 'block_by_action':
+ this.preHandlerDelete(cmt);
+ this.groupModerationRequest('block' + action, idlist);
+ cmt.cobj.action = 'ban';
+ break;
+ case 'unban':
+ if (!this.inlineModeration) {
+ this.preHandlerDelete(cmt);
+ }
+ this.groupModerationRequest(approvalMode, idlist);
+ cmt.cobj.action = 'ban';
+ if (this.inlineModeration) this.postHandlerModerate(cid);
+ break;
+ case 'spam':
+ this.groupModerationRequest(approvalMode, idlist);
+ setTimeout(function() { // screen del
+ s.removeComment(cmt, true);
+ }, 1000);
+ break;
+ case 'ignore':
+ /* Just delete from screen */
+ default:
+ this.removeComment(cmt, true);
+ }
+}
+
+JSCC.prototype.preHandlerDelete = function(cmt) {
+ this.publishEvent('comment-deleting', {'cmtId': cmt.cobj.ID});
+}
+
+JSCC.prototype.postHandlerDelete = function(cmt) {
+ this.publishEvent('comment-deleted', {'cmtId': cmt.cobj.ID});
+}
+
+JSCC.prototype.removeComment = function(cmt, useRecursion) {
+ var cobj = cmt.cobj;
+ var deletedPageIdx = this.jspg.getPageByItemId(cobj.ID);
+ if(cobj.ParentID && this.objById[cobj.ParentID]) {
+ var prn = this.objById[cobj.ParentID];
+ this.jspg.invalidateItemView(cobj.ParentID);
+ var parentPageIdx = this.jspg.getPageByItemId(cobj.ParentID);
+ this.jspg.invalidatePagesView(parentPageIdx, deletedPageIdx-parentPageIdx);
+ } else {
+ if(deletedPageIdx && cobj.ParentID) this.jspg.invalidatePagesView(deletedPageIdx-1, 1);
+ }
+ if(cobj.cedge) {
+ var curItemIdx = this.jspg.getItemIdxById(cobj.ID);
+ if((cobj.cedge==1 && !this.IM && typeof curItemIdx!='undefined') || (cobj.cedge==2 && typeof curItemIdx!='undefined')) {
+ var itemIdxD = cobj.cedge==1 ? 1 : -1;
+ var items = this.jspg.getItems(curItemIdx+itemIdxD, 1);
+ if(items.length && items[0]) items[0].obj.cedge += cobj.cedge;
+ }
+ }
+ var self = this;
+ var deletedComment = function(dobj) {
+ return (dobj.status=='D' || dobj.status=='DT');
+ }
+ var delCount = deletedComment(cobj) ? 0 : 1;
+ if(this.IM) {
+ var cnt = 0;
+ var deletedPageItems = this.jspg.getPageItems(deletedPageIdx);
+ JSKitLib.fmap(deletedPageItems, function(V){
+ if(!deletedComment(V.obj) && V.obj.conversation==cobj.conversation) cnt++;
+ });
+ if(cnt>1) {
+ if(cmt.cobj.hasCnvs) {
+ cmt.cobj.status = 'DT';
+ this.jspg.invalidateItemView(cobj.ID);
+ } else {
+ this.jspg.deleteItem(cmt.cobj.ID);
+ }
+ } else if(cnt<=1){
+ JSKitLib.fmap(deletedPageItems, function(V){
+ if(V.obj.conversation==cobj.conversation) self.jspg.deleteItem(V.obj.ID);
+ });
+ }
+ } else {
+ delCount = this.jspg.deleteItem(cobj.ID);
+ this.reCalcPages();
+ }
+ this.ctag = null;
+ var pageNo = this.curPage;
+ this.curPage = 0;
+ this.displayPage(pageNo, function(immed){
+ if(immed) {
+ if(useRecursion && this.jspg.getItemById(cmt.cobj.ID)) {
+ self.removeComment(cmt);
+ }
+ }
+ });
+ return delCount;
+}
+
+JSCC.prototype.postHandlerModerate = function(cid) {
+ var cmt = this.jspg.getItemById(cid).div;
+ cmt.cobj.status = 'A';
+ this.jspg.invalidateItemView(cid);
+ var pageNo = this.curPage;
+ this.curPage = 0;
+ this.displayPage(pageNo);
+}
+
+JSCC.prototype.createCommentAsHTML = function(obj) {
+ if(obj.status == 'D') return '';
+ if(this.objppc) this.objppc(obj);
+ return this.tmpl(this.dtComment, obj);
+}
+
+JSCC.prototype.getUserProperty = function(name, defaultValue) {
+ return JSKitEPB.getValue(name) || this.TC && this.TC["js-Cmt" + name] && !JHI2.isEmpty(this.TC["js-Cmt" + name]) && this.TC["js-Cmt" + name].value || defaultValue;
+}
+
+JSCC.prototype.markOffensive = function(cid) {
+ if(confirm($JCL("isJunkVote"))) {
+ if ((this.adminMode) && (!this.inlineModeration)) {
+ this.cmtDelete(cid);
+ } else {
+ var item = this.jspg.getItemById(cid);
+ if(!item) return;
+ var obj = item.obj;
+ var req = {
+ 'id': cid,
+ 'permalink': this.config.permalink,
+ 'Text': obj.Text ||
+ (obj.content ? obj.content.title : ''),
+ 'Name': this.getUserProperty("Name", $JCL("guest"))
+ };
+ this.server('-mark.off', req);
+ }
+ }
+}
+
+JSCC.prototype.getLikeInstanceByID = function(cid){
+ var comment = this.jspg.getItemById(cid);
+ return comment.obj.likeInstance;
+}
+
+JSCC.prototype.postLikeVote = function(cid, obj) {
+ var voter = {
+ "name" : this.getUserProperty("Name", "")
+ };
+ var avatar = this.avatarsManager.getActiveAvatar();
+ if (avatar) {
+ voter.avatar = avatar.name;
+ voter.avatar_width = avatar.width;
+ voter.avatar_height = avatar.height;
+ }
+ var likeInstance = this.getLikeInstanceByID(cid);
+ if (likeInstance.busy) return;
+ likeInstance.busy = true;
+ likeInstance.renderLikeControl("progress");
+ likeInstance.sendRequest(voter);
+}
+
+JSCC.prototype.handleLikeResponse = function(cid, action, data){
+ this.routeAction(function() {
+ this.serverOptions.profile = data.profile;
+ var likeInstance = this.getLikeInstanceByID(cid);
+ likeInstance.busy = false;
+ likeInstance.vote(action, data);
+ });
+}
+
+JSCC.prototype.showProfile = function(target, data, extraConfig) {
+ if (data.ProfileURL && !data.profile) {
+ window.open(data.ProfileURL);
+ return;
+ }
+ var s = this;
+ var so = s.serverOptions;
+ if (!data.profile || (data.profile != so.profile && !so.showProfile) || $JSKitGlobal.isProfileLoaded == "no") return;
+ var applyFollowPanelsCallback = function(func) {
+ JSKitLib.fmap([s.followPanel, s.followPanelPopup], function(panel) {
+ if (panel) func(panel);
+ });
+ };
+ var config = JSKitLib.foldl({
+ "parentTarget" : s.target,
+ "targetRef" : JSKitLib.getRef(s),
+ "whiteLabel" : so.whitelabel,
+ "callbacks" : {
+ "onsave" : function(profile) {
+ s.extraFormFields["Email"] = profile.getEmail() || "";
+ var email = s.extraFormFields["Email"] || $JCL("follow_emptyEmail");
+ applyFollowPanelsCallback(function(panel) {
+ var link = panel.get("emailAddress");
+ var action = s.extraFormFields["Email"] ? "remove" : "add";
+ JSKitLib.text(email, link, true);
+ JSKitLib[action + "Class"](link,
+ "js-kit-follow-activeNotifyMode-" + so.notifyMode);
+ });
+ },
+ "onload" : function(profile) {
+ if (profile.isYours()) so.profile = profile.getProfileID();
+ applyFollowPanelsCallback(function(panel) {
+ var link = panel.get("editProfileLink");
+ JSKitLib.text($JCL("follow_editProfile"), link, true);
+ JSKitLib.removeClass(link, "js-kit-follow-openingProfile");
+ JSKitLib.addClass(panel.get("rssThreadButton"), "js-kit-follow-rssButton");
+ });
+ }
+ }
+ }, extraConfig || {}, function(value, acc, key) { acc[key] = value; });
+ if (!$JSKitGlobal.profileObjectInitialized) {
+ $JSKitGlobal.isProfileLoaded = "no";
+ JSKitLib.addScript(s.uriDomain + "/widgets/profile.js", target, function() {
+ $JSKitGlobal.isProfileLoaded = "yes";
+ JSKW$openProfile(data.profile, target, config);
+ });
+ } else JSKW$openProfile(data.profile, target, config);
+}
+
+JSCC.prototype.appendProfileHandler = function(target, data) {
+ var self = this;
+ var isAvailable = this.serverOptions.showProfile && (data.profile || data.ProfileURL);
+ var avatarDims = {"width": "48", "height": "48"};
+ var openProfile = function(element) {
+ JSKitLib.addEventHandler(element, ["click"], function(e) {
+ JSKitLib.stopEventPropagation(e);
+ JSKitLib.preventDefaultEvent(e);
+ self.showProfile(target, data);
+ return false;
+ });
+ };
+ JSKitLib.addClass(target, "js-kit-clickable");
+ if (this.IM || this.getSkin() != "echo") return openProfile(target);
+ if (data.event_publisher) {
+ data.Name = data.content.user.name
+ }
+ var descr = {
+ "avatar": function(element) {
+ var container = {
+ "instance": element,
+ "width": avatarDims.width,
+ "height": avatarDims.height
+ };
+ self.appendAvatarImage(container, data);
+ if (isAvailable) openProfile(element);
+ }
+ };
+ if (isAvailable) descr.name = descr.viewDetails = function(element) { openProfile(element); };
+ var config = {
+ "labels": $JCL,
+ "uriDomain": self.uriDomain,
+ "uriAvatar": self.uriAvatar,
+ "avatarSize": avatarDims,
+ "cssPrefix": "js-kit-singleCmtMiniProfile js-kit-singleCmtProfile" + (isAvailable ? "Enabled" : "Disabled"),
+ "descriptors": descr,
+ "openFullProfile": function() { self.showProfile(target, data); },
+ "isNativeProfileDisabled": !isAvailable
+ };
+
+ eval("var wp = " + JSKitLib.htmlUnquote((data.Webpresence || "[]")));
+ var webpresence = JSKitLib.fmap(wp, function(item) {
+ if (!item[2] || item[2] == "checked") {
+ var type = item[0].replace(/login-/, "");
+ var group = item[0].match(/login-/) ? "login" : "web";
+ if (group == "web" && !self.serverOptions.extraFieldURL) return;
+ var identity = self.jskauth.assembleIdentity(item[1], type, group);
+ if (type == "gfc" && self.jskauth.getAuthIdentity("gfc")) {
+ identity.url = item[1];
+ identity.params.domain = self.config.domain;
+ }
+ return identity;
+ }
+ });
+ var url = data.Url ? [self.jskauth.assembleIdentity(data.Url, "home", "web")] : [];
+ data.identities = {"auth": {}, "web": JSKitLib.merge(webpresence, url)};
+
+ var clearTimer = function(timer) {
+ clearTimeout(timer);
+ timer = undefined;
+ };
+ var openMiniProfile = function(ttl) {
+ clearTimer(self.miniProfileCollapseTimer);
+ self.miniProfileExpandTimer = setTimeout(function() {
+ if (data.miniProfile) {
+ data.miniProfile.display(target);
+ } else {
+ data.miniProfile = new JSKitMiniProfile(target, data, config);
+ }
+ data.miniProfile.getContent().onmouseover = function() {
+ clearTimer(self.miniProfileCollapseTimer);
+ };
+ }, ttl);
+ };
+ target.onclick = function() { openMiniProfile(0); }
+ target.onmouseover = function() { openMiniProfile(JSCC.MINI_PROFILE_TTL); }
+ target.onmouseout = function() {
+ clearTimer(self.miniProfileExpandTimer);
+ self.miniProfileCollapseTimer = setTimeout(function() {
+ JSKW$Events.syncBroadcast("miniProfile_collapseAll");
+ }, JSCC.MINI_PROFILE_TTL);
+ };
+}
+
+JSCC.prototype.fixComment = function(cmt, obj, pageIdx, globalIdx, itemsOnPage) {
+ var self = this;
+ if (obj.profile == this.serverOptions.profile) obj.yours = true;
+ var so = this.serverOptions;
+ var cfg = this.config;
+ var typeCondition = obj.msgtype && obj.msgtype.match(/T|P/) && !so.trackbackreply;
+ var flagCondition = !so.commod || obj.yours || cfg.nolc || typeCondition;
+ var anonymous = so.anonymousCmt && !self.jskauth.isLogged();
+
+ self.objById[obj.ID] = obj;
+ if(obj.status == 'D') {
+ cmt.style.display = 'none';
+ return;
+ }
+
+ if(obj.depth) {
+ cmt.style.marginLeft = this.level4margin(obj.depth)
+ } else {
+ obj.depth = 0;
+ }
+
+ var ctls = JSKitLib.mapClass2Object({}, cmt);
+ cmt.ctls = ctls;
+ cmt.cobj = obj;
+ var imgArea = cmt.ctls["js-singleCommentPreviewImage"];
+ if (imgArea && cmt.cobj.imgs && cmt.cobj.imgs.length && self.config.uploadImages){
+ self.addChild(imgArea,self.createImages(cmt.cobj.imgs));
+ imgArea.style.display = "block";
+ }
+
+ var jsc = function(t){return ctls['js-singleComment'+t]}
+
+ var switchClasses = function(controls, class2add, class2remove) {
+ JSKitLib.fmap(controls, function(element) {
+ JSKitLib.addClass(element, class2add);
+ JSKitLib.removeClass(element, class2remove);
+ });
+ };
+
+ var appendHoverActions = function(controls){
+ var container = jsc("");
+ if (!container || self.getSkin() != "echo") return;
+ JSKitLib.addEventHandler(container, ["mouseout"], function() {
+ switchClasses(controls, "jsk-SecondaryFontColor", "jsk-LinkColor");
+ });
+ JSKitLib.addEventHandler(container, ["mouseover"], function() {
+ switchClasses(controls, "jsk-LinkColor", "jsk-SecondaryFontColor");
+ });
+ };
+
+ cmt.bg = jsc('Bg');
+ var stripe = jsc('Body') || jsc('');
+ stripe.className += " js-singleCommentDepth" + (obj.depth || 0);
+ if (this.useEcho()) {
+ if (obj.depth) {
+ stripe.className += " jsk-TrinaryBackgroundColor jsk-ItemWrapperChild";
+ switchClasses([cmt.bg], 'jsk-TrinaryBackgroundColor', 'js-singleCommentBg');
+ } else if (obj.thread && obj.thread.length) {
+ stripe.className += " jsk-ItemWrapperThread";
+ }
+ }
+ if(!(cmt.style.display.match(/none/))){
+ stripe.className += " js-comment-stripe-" + ((globalIdx % this.stripecount) + 1);
+ }
+
+ if(self.IM && typeof(obj.conversation)=='number') {
+ if(obj.hasCnvs) {
+ this.appendConversation(cmt, obj.conversation);
+ } else {
+ this.appendConversationChild(cmt);
+ }
+ }
+
+ /* Handle avatars */
+ if(obj.status!='DT' && obj.status!='DD') self.placeAvatar(obj, jsc('Avatar'));
+
+ /* Handle if ratings are present */
+ if (obj.Rating > 0 && ( ! this.isStandalone()) ) {
+ var self = this;
+ var action = function() {
+ if (!jsc('Rating')) return;
+ jsc('Rating').appendChild(self.createMiniStarObject(obj.Rating, 10));
+ jsc('Rating').appendChild(JSKitLib.html('
'));
+ JSKitLib.show(jsc('Rating'));
+ }
+ $JSKitGlobal.tryRatingsAppObjectAction(this.uniq, action);
+ } else {
+ if (jsc('Rating')) JSKitLib.hide(jsc('Rating'));
+ }
+
+ var sa = jsc("Name");
+ if(sa) {
+ self.rerenderName(cmt);
+ if(obj.admin) sa.className = sa.className + " js-siteAdmin";
+ }
+
+ var renderKarmaView = function(karma, container, value, voters) {
+ JSKitLib.text(karma.score, value, true);
+ JSKitLib.text(karma.votesText, voters, true);
+ JSKitLib.show(container, "inline");
+ };
+ var kS = jsc("KarmaScore");
+ if(kS && obj.karma) {
+ var kVal = jsc("KarmaValue");
+ var kVot = jsc("KarmaVoters");
+ if(obj.karma.votes) renderKarmaView(obj.karma, kS, kVal, kVot);
+ var setKarmaAction = function(name, score) {
+ if (!jsc(name)) return;
+ JSKitLib.setEventHandler(jsc(name), ['click'], function() {
+ obj.karma.recomputeScore(score);
+ renderKarmaView(obj.karma, kS, kVal, kVot);
+ this.blur();
+ });
+ }
+ setKarmaAction("KarmaY", 1);
+ setKarmaAction("KarmaN", -1);
+ }
+ if(jsc("KarmaShow") && obj.karma && obj.yours && obj.karma.votes) {
+ renderKarmaView(obj.karma, jsc("KarmaShow"), jsc("KarmaValueShow"), jsc("KarmaVotersShow"));
+ }
+ if (so.likedBy && jsc("LikedBy")){
+ var anonymousAvatar = self.avatarsManager.anonymousAvatarData();
+ eval("var votersList = " + (obj.like || "[]") + ";");
+ obj.likeInstance = new JSCCLike({
+ "ID" : obj.ID,
+ "jx": self.jcaIndex,
+ "ref": JSKitLib.getRef(self),
+ "path": self.pathOverride,
+ "voters" : votersList,
+ "target" : jsc("LikedBy"),
+ "profile": function(){ return self.serverOptions.profile; },
+ "translator" : $JCL,
+ "onInit" : function(){
+ var expandMarker = this.getExpandMarker();
+ if (expandMarker) appendHoverActions([expandMarker]);
+ },
+ "onVoterInit" : function(target, data){
+ var avatar = data.avatarData || anonymousAvatar;
+ data.avatar = avatar.name;
+ data.avatarWidth = avatar.width;
+ data.avatarHeight = avatar.height;
+ delete data.avatarData;
+ self.appendProfileHandler(target, data);
+ },
+ "onVoterRender" : function(dom, data){
+ self.avatarsManager.assembleAvatar({
+ "instance": dom.get("avatar"),
+ "width": "16",
+ "height": "16"
+ }, data.avatar || anonymousAvatar);
+ },
+ "likeControl": jsc("Like")
+ });
+ }
+
+ var functionsToBind = [
+ ["Edit", "ShowCommentDialog", [{isEditing: true}]],
+ ["Flag", "markOffensive"],
+ ["Like", "postLikeVote"],
+ ["Reply", "ShowCommentDialog"],
+ ["Block", "cmtBlock"],
+ ["Delete", "cmtDelete"],
+ ["Approve", "cmtApprove"],
+ ["Moderate","cmtBlock"],
+ ["ComModMark", "markOffensive"],
+ ["ApproveUser", "cmtApproveUser"]
+ ];
+
+ JSKitLib.fmap(functionsToBind, function(list){
+ (function(elementName, funcName, args) {
+ if (!jsc(elementName)) return;
+ args = args || [];
+ args.unshift(cmt.id);
+ JSKitLib.setEventHandler(jsc(elementName), ['click'], function(){
+ self[funcName].apply(self, args);
+ });
+ }).apply(self, list);
+ });
+
+ var elementVisibilityConditions = {
+ "IP" : !self.adminMode,
+ "Url" : obj.Url,
+ "Karma" : !this.scoringEnabled() || obj.yours || !obj.karma || typeCondition || cfg.nolc,
+ "ComMod" : flagCondition,
+ "LikedBy" : !so.likedBy,
+ "Editable" : cfg.editable != 'yes' || cfg.nolc || !(self.adminMode || self.ownerMode),
+ "Likeable" : !so.likedBy || anonymous,
+ "Flagable" : flagCondition,
+ "Deletable" : (!self.adminMode || !obj.event_type) && ((!obj.yours && !self.IM && !self.ownerMode) || (self.adminMode && !cfg.nolc)),
+ /* FIXME(?) Lev, this.serverOptions are not defined in moderation mode but the result is likely as desired, i.e. admin can still reply */
+ "Replyable" : so.mmode == "pause" || !self.isSourceAvailable("Comments") || typeCondition || (cfg.nolc && (!self.IM || obj.yours)),
+ "Moderatable" : !self.adminMode || cfg.nolc,
+ "ApproveUser" : so.mmode != "onhold",
+ "ProfileLinkable" : !obj.profile || cfg.nolc
+ };
+ JSKitLib.fmap(elementVisibilityConditions, function(flag, name){
+ if (jsc(name) && flag) JSKitLib.hide(jsc(name));
+ });
+
+ cmt.bg.style.zIndex = this.czidx - (pageIdx % this.czidx);
+ cmt.domINFO = jsc('INFO');
+ cmt.domCtls = jsc('Ctls') || jsc('controls');
+
+ if(obj.status == 'S')
+ this.cmtSetSpamStatus(cmt, true);
+
+ if(obj.status == 'O')
+ this.cmtSetOffensiveStatus(cmt, true);
+
+ if(obj.admin) {
+ JSKitLib.addClass(cmt, "js-commentByAdmin");
+ if(cfg.adminBgColor) {
+ cmt.style.backgroundColor = cfg.adminBgColor;
+ cmt.bg.style.backgroundColor = cfg.adminBgColor;
+ }
+ var star = jsc('AdminStar');
+ if(star) JSKitLib.show(star, 'inline');
+ }
+
+ if(obj.status == 'DT') {
+ if(cmt.domINFO) JSKitLib.hide(cmt.domINFO);
+ if(cmt.domCtls) JSKitLib.hide(cmt.domCtls);
+ }
+ if(obj.status == 'DD') {
+ if(cmt.domCtls) JSKitLib.hide(cmt.domCtls);
+ this.placeProcessAvatar(jsc('Avatar'));
+ }
+ if(jsc("Checkbox")) {
+ var checkbox = jsc("Checkbox");
+ var state = this.moderationCommentsList[obj.ID] ? "checked" : "unchecked";
+ this.setInputState("checkbox", checkbox, state);
+ checkbox.onclick = function() {
+ var state = self.moderationCommentsList[obj.ID] ? "unchecked" : "checked";
+ self.setInputState("checkbox", checkbox, state);
+ self.moderationCommentsListUpdate(obj.ID, state == "checked");
+ };
+ }
+ if(jsc("Menu")) {
+ if(!obj.menu)
+ obj.menu = self.addMenu(cmt, obj);
+ if(obj.menu)
+ jsc("Menu").appendChild(obj.menu);
+ }
+ if(jsc("ViaIcon")) JSKitLib.addPNG(jsc("ViaIcon"), obj.content.service.iconUrl);
+ var controls = JSKitLib.fmap(["Flag", "Like", "Reply", "Moderate", "Edit", "Delete", "ViaThirdPartyService"], function(name){
+ var element = jsc(name);
+ if (element) return element;
+ });
+ appendHoverActions(controls);
+}
+
+JSCC.prototype.setInputState = function(type, element, state) {
+ JSKitLib.addPNG(element, "//cdn.js-kit.com/images/common/" + type + "_" + state + ".png");
+}
+
+JSCC.prototype.level2margin = function(level) {
+ if(level < 20) return "10px";
+ if(level < 40) return "4px";
+ return "0px";
+}
+JSCC.prototype.level4margin = function(level) {
+ switch (this.config.skin) {
+ case 'echo':
+ if(level > 1) level = 1;
+ return ((parseInt(this.maxAvatarDims.width) + 10) * level) + 'px';
+ default:
+ if(level <= 20) return (10 * level) + 'px';
+ if(level <= 40) return (200 + 4 * level) + 'px';
+ return '280px';
+ }
+}
+JSCC.prototype.cmtInDiv = function(div, obj, fincb) {
+ JSKW$Events.syncBroadcast("smileys-newCommentInDiv", obj);
+ if (!obj.isEditing) {
+ var cIdx, insBefore = false;
+ if(this.config.backwards == 'yes') {
+ var fitem = this.jspg.getFirstItem();
+ if(fitem) {
+ cIdx = fitem.obj.ID;
+ insBefore = true;
+ }
+ }
+ if(this.config.thread != 'yes') {
+ obj.Notice = $JCL('commentMoveNotice');
+ cIdx = obj.ParentID || cIdx;
+ delete obj.ParentID;
+ delete obj.depth;
+ }
+ if(this.useEcho()) {
+ cIdx = this.jspg.getPlaceIdxByTS(obj.TS);
+ insBefore = true;
+ }
+ obj.cedge = 3;
+ if(obj.ParentID) {
+ obj.cedge = 0;
+ var prn = this.objById[obj.ParentID];
+ var td = (prn && prn.depth) ? prn.depth : 0;
+ if(prn) {
+ if (this.useEcho()) {
+ JSKitLib.addClass(this.jspg.getItemById(obj.ParentID).div, 'jsk-ItemWrapperThread');
+ }
+ if(!obj.depth) {
+ prn.thread.push(obj);
+ obj.depth = 1 + td;
+ }
+ if(this.IM && typeof(prn.conversation)=='number') obj.conversation = prn.conversation;
+ cIdx = this.getLastReply(obj.ParentID).obj.ID;
+ insBefore = false;
+ var curItem = this.jspg.getItemById(cIdx);
+ if(curItem && curItem.obj.cedge>1) {
+ obj.cedge = 2;
+ curItem.obj.cedge -= 2;
+ var parentPageIdx = this.jspg.getPageByItemId(obj.ParentID);
+ var insertedPageIdx = this.jspg.getPageByItemId(cIdx);
+ this.jspg.invalidatePagesView(parentPageIdx, insertedPageIdx-parentPageIdx+1);
+ }
+ }
+ }
+
+ if(this.IM) {
+ for(var i=0; i 0) {
+ cmt.cobj.height += cmtHeight;
+ cmt.style.height = cmt.cobj.height + 'px';
+ return true;
+ } else if (cmt.cobj.cntBorderPause == 8) {
+ cmt.style.overflow = "";
+ cmt.style.height = "";
+ cmt.cobj.height = -1;
+ cmt.cobj.cntBorderPause--;
+ return true;
+ } else if (cmt.cobj.cntBorderPause > 0) {
+ cmt.cobj.cntBorderPause--;
+ return true;
+ } else if (cmt.cobj.cntBorderUp < 256) {
+ cmt.cobj.cntBorderUp += 10;
+ var blue = cmt.cobj.cntBorderUp;
+ bg.style.backgroundColor = "rgb(256, 256, " + (blue > 256 ? 256 : blue) + ")";
+ return true;
+ } else {
+ self.setOpacity(bg, 1);
+ bg.style.backgroundColor = "";
+ delete cmt.cobj.echoItemFirstTime;
+ return false;
+ }
+ }
+ var oldEffectStep = function(cmt) {
+ if (cmt.cobj.cntDown > 0) {
+ self.setOpacity(bg, calcOpacity());
+ return true;
+ } else {
+ bg.style.backgroundColor = "";
+ self.setOpacity(bg, 1);
+ return false;
+ }
+ }
+ cmt.cobj.cntDown -= cmt.cobj.cntMode ? decr.f : decr.s;
+ return cmt.cobj.echoItemFirstTime ? echoEffectStep(cmt) : oldEffectStep(cmt);
+ }
+
+ var runStep = function() {
+ obj.intvl = setTimeout(function() {
+ var nextStep = effectStep(cmt);
+ if (nextStep) runStep();
+ else {
+ obj.intvl = null;
+ delete obj.havingEffect;
+ }
+ }, 50);
+ };
+ runStep();
+}
+
+JSCC.prototype.foldInputFields = function(e, acc, f) {
+ if(e.getAttribute) {
+ var name = e.getAttribute('NAME');
+ if(name && (name.substr(0, 6) == 'js-Cmt')) {
+ var shortName = name.substr(6);
+ acc = f.call(this, e, acc, shortName) || acc;
+ }
+ }
+ var cn = e.childNodes;
+ if(cn) {
+ var clen = cn.length;
+ for(var i = 0; i < clen; i++)
+ acc = this.foldInputFields(cn[i], acc, f);
+ }
+ return acc;
+}
+
+JSCC.prototype.inputFieldsMsg = function(ctl, cmtObj, pText) {
+ return this.foldInputFields(ctl, [], function(e, a, name){
+ if (e.jsk$not_specified || JHI2.isEmpty(e)) return;
+ var isText = /^Text(Edit)?$/.test(name);
+ var text = isText ? pText : e.value;
+ a.push({"Name": "js-Cmt" + name, "Value": text});
+ if(isText && this.serverOptions.htmlMode)
+ text = text.replace(/<[\/]?[a-z]{1,3}(\s+(href)=[^>]+)?>/g, '');
+ //text = text.replace(/&/g, '&').replace(//g, '>');
+ cmtObj[name] = text;
+ });
+}
+
+JSCC.prototype.cmtAvatarPlaceWidth = function(cobj) {
+ return cobj.ParentID ? this.maxAvatarDims.width/2 : this.maxAvatarDims.width;
+}
+
+JSCC.prototype.cmtInPlace = function(cobj, fincb) {
+ var div = this.TC["js-OldComments"];
+ cobj.Name = cobj.Name || $JCL("guest");
+ this.cmtInDiv(div, cobj, function(cmt) {
+ if(cmt) this.flash(cmt);
+ if(fincb) fincb.apply(this, [cmt]);
+ });
+}
+
+JSCC.prototype.ShowCommentDialog = function(msgId, extra) {
+ if(this.commentPostingProcess) {
+ alert($JCL('messagePostingInProgress'));
+ return;
+ }
+ var s = this;
+ msgId = msgId || '';
+ this.forMsg = this.objById[msgId];
+
+ /* Remove dialog from sight */
+ this.CommentCancelled();
+
+ extra = extra || {};
+ if (s.getSkin() == "echo") {
+ if (this.TC["js-CmtText"] && (this.jskauth.isLogged() || !this.anonymousCmt)) {
+ var hint = $JCL("defaultCommentText");
+ var input = s.TC["js-CmtText"];
+ if (s.serverOptions.wysiwyg) {
+ hint = '' + hint + ' ';
+ input.hint = hint;
+ input.value = hint;
+ } else {
+ JHI2.remove(input);
+ JHI2.create(hint, input);
+ }
+ }
+ JSKitLib.fmap(s.serverOptions.wysiwyg ? [] : ["js-CmtText", "js-CmtTextEdit", "jsk-CommentFormBody", "jsk-CommentEditFormBody"], function(name) {
+ if (s.TC[name]) JSKitLib.addClass(s.TC[name], name + "-noWYSIWYG");
+ });
+ }
+
+ var isReply = !!msgId;
+ var cct = this.TC["js-LeaveComment"];
+
+ if (!this.getSkin().match(/smoothgray|echo/)) this.onAddImgButton(this.imgShow);
+
+ var ccd = this.TC[extra.isEditing ? "js-EditComment" : "js-CreateComment"];
+ if (extra.isEditing) {
+ isReply = false;
+ var cte = this.TC['js-CmtTextEdit'];
+ if (this.forMsg.originalText) {
+ cte.value = this.forMsg.originalText;
+ } else {
+ cte.value = this.forMsg.Text.replace(/<\/wbr>/g, '');
+ if (!this.serverOptions.wysiwyg) {
+ cte.value = JSKitLib.htmlUnquote(cte.value);
+ JSKW$Events.syncBroadcast("smileys-beforePostNewComment", cte);
+ }
+ }
+ }
+ this.replyForId = (isReply ? msgId : '');
+
+ var placeDialog = function(immediate, apl) {
+ if (!apl) apl = [this.TC["js-CommentsArea"], this.TC["js-CommentsArea"].firstChild];
+ if(msgId){
+ apl[0].insertBefore(ccd, apl[1]);
+ } else if (this.config.backwards == 'yes') {
+ apl[0].insertBefore(ccd, this.TC['js-WelcomePanel'] ? apl[1].nextSibling : apl[1]);
+ } else {
+ this.addChild(apl[0], ccd);
+ }
+ if (extra.isEditing) JSKitLib.hide(apl[1]);
+
+ if(this.config.backwards == 'yes' && msgId)
+ cct.style.visibility = "hidden";
+ else
+ cct.style.display = "none";
+ ccd.style.display = "block";
+ try {
+ var name_suffix = (extra.isEditing ? 'Edit' : '');
+ var text = this.TC["js-CmtText" + name_suffix];
+ /* TinyMCE support (A) */
+ if(!text.id) text.id = "js-CmtText" + name_suffix + "-" + this.jcaIndex;
+ if(!text.richEditor && this.serverOptions.wysiwyg) try {
+ text.smoothWysiwygLoading = (s.getSkin() == 'echo' && !extra.isEditing);
+ if (text.smoothWysiwygLoading) {
+ if (!text.jsk$cover) {
+ text.jsk$cover = JSKitLib.html('');
+ text.jsk$wrapper = s.TC['jsk-CommentFormBody'];
+ }
+ text.jsk$wrapper.parentNode.replaceChild(text.jsk$cover, text.jsk$wrapper);
+ JSKitLib.hide(text.jsk$wrapper);
+ text.jsk$cover.parentNode.insertBefore(text.jsk$wrapper, text.jsk$cover);
+ }
+ var addMCECtrl = function(){
+ text.jsk$nofocus = extra.nofocus;
+ text.jsk$widget = s;
+ if(s.tmce.foreign) tinyMCE.settings = s.tmce.cfg;
+ tinyMCE.settings.auto_focus = (extra.nofocus ? null : text.id);
+ text.jsk$hasDefaultValue = (s.getSkin() == 'echo' && !extra.isEditing);
+ if (text.jsk$hasDefaultValue) {
+ var re = new RegExp('()?' + text.hint + '(
)?');
+ text.defaultRemoved = !text.value.match(re);
+ }
+ tinyMCE.execCommand('mceAddControl', false, text.id);
+ text.richEditor = true;
+ if(text.mceLoadedCtx) {
+ JSKW$Events.invalidateContext(text.mceLoadedCtx);
+ text.mceLoadedCtx = null;
+ }
+ }
+ if(window.tinyMCE) {
+ if(tinyMCE.getInstanceById(text.id) == null) {
+ setTimeout(function() { addMCECtrl(); }, 0);
+ }
+ } else text.mceLoadedCtx = JSKW$Events.registerEventCallback(undefined, addMCECtrl, "mceLoaded");
+ } catch(e) {}
+
+ var sub = this.TC["js-Cmtsubmit" + name_suffix];
+ var can = this.TC["js-Cmtcancel" + name_suffix];
+ var prev = function(e){JSKitLib.stopEventPropagation(e); JSKitLib.preventDefaultEvent(e); return false;}
+
+ if(JSKitLib.isOpera()) {
+ var onkey = function(){};
+ } else if(JSKitLib.isIE()) {
+ var onkey = function(d,f){d.onkeydown=f};
+ } else {
+ var onkey = function(d,f){d.onkeypress=f};
+ }
+
+ /* combined ratings */
+ var commentRatingElements = JSKitLib.getElementsByClass(ccd, "js-commentRatingDisplay");
+ var commentRatingDisplay = 'none';
+ this.submitRating = false;
+ if (this.hasRatingsAppObject() && ( ! isReply)) {
+ if (this.TC["js-commentFieldRating"]) {
+ this.embedRatingsAppObject(this.TC["js-commentFieldRating"]);
+ commentRatingDisplay = '';
+ this.submitRating = true;
+ }
+ }
+ for (var i=0; i < commentRatingElements.length; i++) {
+ commentRatingElements[i].style.display = commentRatingDisplay;
+ }
+
+
+ var flds = this.foldInputFields(ccd, [],
+ function(e, a, name) {
+ var dfl = this.fieldDfl[name];
+ if(dfl) {
+ if(e.jsk$setdfl)
+ e.jsk$setdfl(dfl);
+ else if(!e.value)
+ e.value = dfl;
+ }
+ var aclen = a.length;
+ if(e.richEditor) {
+ if (e.value) {
+ e.value = e.value.replace(/^\n\n+/, '');
+ if(!e.value.match(/^(\n|.)*<\/p>$/)) e.value = '
' + e.value + '
';
+ }
+ var o = { focus: function() {
+ var setupFocusing = function(ed) {
+ var keyHandler = function(ed, e) {
+ if(e.keyCode != 9) return true;
+ window.focus();
+ try {
+ a[aclen+(e.shiftKey?-1:1)].focus();
+ } catch(ex) { ; }
+ return prev(e);
+ };
+ if (JSKitLib.isIE()) ed.onKeyDown.add(keyHandler); else ed.onKeyPress.add(keyHandler);
+ }
+ var ed = tinyMCE.getInstanceById(text.id);
+ if(ed) {
+ setupFocusing(ed);
+ } else {
+ var t = setInterval(function() {
+ var ed = tinyMCE.getInstanceById(text.id);
+ if(ed) { clearInterval(t); setupFocusing(ed); }
+ }, 100);
+ }
+ } };
+ if(aclen) onkey(a[aclen-1], function(e) {
+ e = e || window.event;
+ if(e.keyCode == 9 && !e.shiftKey) {
+ this.blur();
+ o.focus();
+ return prev(e);
+ }
+ });
+ a.push(o);
+ } else {
+ a.push(e);
+ }
+ });
+
+ var okd = function(offset) { return function(e) {
+ e = e || window.event;
+ if(e.keyCode != 9) return true;
+ this.blur();
+ flds[offset+(e.shiftKey?(flds.length-2):0)].focus();
+ return prev(e);
+ } }
+
+ onkey(flds[flds.length-1], okd(0));
+ onkey(flds[0], okd(1));
+
+ // Place initial focus.
+ if(!extra.nofocus) {
+ for(var i = 0; i < flds.length; i++)
+ if(!flds[i].value || flds[i].type == 'submit') {
+ flds[i].focus();
+ break;
+ }
+ if (s.config.backwards != 'yes')
+ sub.scrollIntoView(false);
+ }
+ } catch(e) { }
+ };
+ if(!msgId) {
+ placeDialog.apply(this,[true]);
+ } else {
+ var id = this.useReplyThreadsCollapsing() || extra.isEditing ?
+ msgId : this.getLastReply(msgId).obj.ID;
+ var pn = this.jspg.getPageByItemId(id);
+ var item = this.jspg.getItemById(id);
+ item.obj.isEditing = extra.isEditing;
+ this.displayPage(pn+1, function(immed) {
+ if (!immed) return;
+ if (!s.useEcho()) item = s.jspg.getItemById(id);
+ var placement = [item.div.parentNode, item.div.nextSibling];
+ if (extra.isEditing) {
+ s.editingCmt = item.div.ctls['js-singleCommentText'];
+ placement = [s.editingCmt.parentNode, s.editingCmt];
+ }
+ placeDialog.apply(s, [true, placement]);
+ });
+ s.setStreamState(true, true);
+ }
+ var pb = this.TC["js-poweredBy-echo"] || this.TC["js-poweredByJSKit"];
+ if (this.serverOptions.whitelabel && pb) JSKitLib.hide(pb);
+
+ if (s.getSkin() != 'echo') {
+ var oiddiv = s.TC['js-logoutSpan'];
+ if (oiddiv) oiddiv.style.display = s.jskauth.isLogged() ? 'inline' : 'none';
+ s.jskauth.drawSelector(s.TC['js-authSelector']);
+ s.setThirdPartyShare();
+ s.setNameFieldValue();
+ }
+ return false;
+}
+
+JSCC.prototype.CommentCancelled = function() {
+ if(this.tmce && (this.serverOptions.media || this.serverOptions.smiley))
+ this.tmce.cfg.closePopups();
+ var cct = this.TC["js-LeaveComment"];
+ var ccd = [this.TC["js-EditComment"], this.TC["js-CreateComment"]];
+ if (cct) {
+ cct.style.visibility = "";
+ cct.style.display = "";
+ }
+ var name_suffix = (this.editingCmt ? 'Edit' : '');
+ var text = this.TC["js-CmtText" + name_suffix];
+ if(text && text.richEditor) {
+ try {
+ if (!this.anonymousCmt) {
+ tinyMCE.triggerSave(false, false);
+ }
+ var v = text.value;
+ tinyMCE.execCommand('mceRemoveControl', false, text.id); //tmce set value from its internal property
+ text.value = v;
+ } catch(e) { ; };
+ text.richEditor = false;
+ if(text.mceLoadedCtx) {
+ JSKW$Events.invalidateContext(text.mceLoadedCtx);
+ text.mceLoadedCtx = null;
+ }
+ }
+ var s = this;
+ JSKitLib.fmap(ccd, function(el, i){
+ el && el.parentNode && el.parentNode.removeChild(el);
+ });
+ if (this.editingCmt) {
+ JSKitLib.show(this.editingCmt);
+ delete this.editingCmt;
+ }
+ return false;
+}
+
+JSCC.prototype.smileTag = function(smile) {
+ return ' ';
+}
+
+JSCC.prototype.textSmiles2Graphical = function(text, reverse) {
+ var s = this;
+ if(window.tinyMCE) tinyMCE.settings.smiley = false;
+ var flag = true;
+ var orig = text;
+ JSKitLib.fmap(s.smiles, function(el, i){
+ text = reverse ? text.replace(el.regexpTag, ' ' + i + ' ') : text.replace(el.regexpText, function($0, $1){return ($1 ? $0 : s.smileTag(el));});
+ if(window.tinyMCE && flag && (text !== orig)) {
+ tinyMCE.settings.smiley = true;
+ flag = false;
+ }
+ });
+ return text;
+}
+
+JSCC.prototype.thirdPartyImport = function(KVLMsg) {
+ var s = this;
+ var text = JSKitLib.stripTags(KVLMsg['js-CmtText']);
+ var permalink = KVLMsg['permalink'] || s.config.permalink;
+ var reg = RegExp("^http(.)?://(.*?)/");
+ var m = reg.exec(permalink);
+ var domain = (m && m.length>1) ? m[2] : s.config.domain;
+ var share_data = {
+ 'domain': domain,
+ 'permalink': permalink,
+ 'Text': text
+ };
+ var createTargetDiv = function() {
+ var tgt = 'div-sharing-' + Math.random();
+ var div = JSKitLib.html('
');
+ s.target.appendChild(div);
+ return tgt;
+ }
+ var facebook = s.jskauth.getAuthIdentity("facebook");
+ if(facebook && KVLMsg['js-CmtShare-facebook']=='on') {
+ var jsk$fb = new JSKitFBSDK(
+ JSKitLib.getRef(s),
+ facebook.params.app_id,
+ facebook.params.xd_receiver,
+ function() {
+ this.shareComment(s.serverOptions.whitelabel);
+ },
+ undefined,
+ share_data);
+ }
+ var gfc = s.jskauth.getAuthIdentity("gfc");
+ if(gfc && gfc.params.site && KVLMsg['js-CmtShare-gfc']=='on') {
+ var jsk$gfc = new JSKitGFC(
+ JSKitLib.getRef(s),
+ createTargetDiv(),
+ gfc.params.site,
+ function(){
+ this.sharedata = share_data;
+ this.shareComment();
+ });
+ }
+}
+
+JSCC.prototype.appendFormFields = function(fields, tmpObj) {
+ var self = this;
+ var formFields = this.getKVListFromMsg(fields);
+ var extraFields = JSKitLib.foldl({}, this.extraFormFields, function(value, acc, name) {
+ if (name != "Email" || self.getSkin() != "echo") acc["js-Cmt" + name] = value;
+ });
+ var mergedFields = JSKitLib.foldl(extraFields, formFields, function(value, acc, name) { acc[name] = value; });
+ return JSKitLib.fmap(mergedFields, function(value, name) {
+ tmpObj[name.replace("js-Cmt", "")] = value;
+ return {"Name": name, "Value": value};
+ });
+}
+
+JSCC.prototype.CommentSubmitted = function() {
+ var s = this;
+ var prn = this.forMsg;
+ var isEditing = prn && prn.isEditing;
+
+ if(!isEditing && this.serverOptions.requireUsername && this.TC["js-CmtName"] && JHI2.isEmpty(this.TC["js-CmtName"])) {
+ alert($JCL('nicknameRequired'));
+ s.TC["js-CmtName"].focus();
+ return;
+ }
+
+ /* TinyMCE support (B) */
+ var name_suffix = (isEditing ? 'Edit' : '');
+ var text = this.TC["js-CmtText" + name_suffix];
+ var textValue;
+ if(text.richEditor) {
+ tinyMCE.triggerSave(false, false);
+ JSKW$Events.syncBroadcast("smileys-beforePostNewComment", text);
+ textValue = String(text.value).
+ replace(/(<\/p>)[\r\n]+()/g, '$1$2').
+ replace(/(
) (<\/p>)/g, '$1$2').
+ replace(/
/g, '\n').replace(/<\/p>/g, '').replace(/ /g, '\n').
+ replace(/^\n/, '');
+ } else {
+ textValue = String(text.value).replace(/&/g, '&');
+ }
+
+ var textMsg = (this.getSkin() != "echo" || !JHI2.isEmpty(text)) ? encodeURIComponent(textValue) : "";
+ if(!textMsg || !textMsg.length) {
+ alert($JCL("tooShort"));
+ return;
+ }
+
+ var mcl = this.serverOptions.maxCommentLength || 3000;
+ if(text.value.length > mcl) {
+ alert($JCL("tooLong",{"maxCommentLength":mcl}));
+ return;
+ }
+
+ var form = this.TC[isEditing ? "js-EditComment" : "js-CreateComment"];
+ var avt = this.avatarsManager.getActiveAvatar() || 'no';
+ var permalink = this.config.permalink;
+ var moderate = this.config.moderate;
+
+ var tmpObj = {yours:true};
+ if(prn) {
+ if (isEditing) {
+ tmpObj.ID = prn.ID;
+ } else {
+ tmpObj.ParentID = prn.ID;
+ }
+ tmpObj.path = prn.path;
+ if(prn.permalink) {
+ tmpObj.permalink = prn.permalink;
+ permalink = prn.permalink;
+ }
+ }
+
+ if (this.getSkin() == "echo" && this.extraFormFields["Url"] && this.jskauth.isLogged()) {
+ this.extraFormFields["Url"] = "";
+ }
+ this.extraFormFields["Name"] = this.getUserProperty("Name", "");
+ this.extraFormFields["Email"] = this.getUserProperty("Email", "");
+ this.extraFormFields["Webpresence"] = this.getSelectedIdentities();
+
+ var message = this.appendFormFields(this.inputFieldsMsg(form, tmpObj, textValue), tmpObj);
+ if (this.getSkin() == "echo") {
+ message.push({'Name': 'js-CmtNotifyMode', 'Value': s.serverOptions.notifyMode});
+ }
+
+ tmpObj["Name"] = tmpObj["Name"] || $JCL("guest");
+
+ /* combined ratings */
+ if (this.submitRating) {
+ rating = this.getRatingsAppObject().userRating;
+ message.push({'Name': 'js-CmtRating', 'Value': rating});
+ tmpObj.Rating = rating;
+ }
+ if(prn && !isEditing) {
+ message.push({'Name': 'js-CmtParentID', 'Value': prn.ID});
+ if(this.IM=='own' && prn.profile) {
+ message.push({'Name': 'destProfile', 'Value': prn.profile});
+ }
+ }
+ if(permalink) message.push({'Name': 'permalink', 'Value': permalink});
+ if (!isEditing) {
+ if(avt) message.push({'Name': 'avatar', 'Value': (avt.name ? avt.name : avt)});
+ } else {
+ tmpObj.isEditing = true;
+ }
+
+ if(moderate) this.pathOverride = this.forMsg.path;
+
+ var onsuccess = function(cmtObj) {
+ var KVLCmt = s.getKVListFromMsg(message);
+ // API: subscriber expects
+ // (ConstructedMessageObject[, FormDOM])
+ try {
+ JSKitAPI.askpublic.call(s, "comment-submit",
+ s.generateEventParams(KVLCmt), form);
+ } catch(e) {
+ return;
+ }
+ s.CommentCancelled();
+ if (s.TC['js-CmtText' + name_suffix]) {
+ s.TC['js-CmtText' + name_suffix].value = '';
+ }
+ if (s.clearImgs) {
+ s.clearImgs();
+ }
+ if (!isEditing) {
+ s.thirdPartyImport(KVLCmt);
+ }
+ if (s.extraControlsMenu) {
+ s.extraControlsMenu.collapseTabs();
+ }
+ var am = s.avatarsManagement;
+ if (am && am.avatarsListContainer) {
+ JSKitLib.hide(am.avatarsListContainer);
+ }
+ delete s.replyForId;
+ }
+ var onerror = function() {
+ var cover = s.commentPostingProcess.cover;
+ if (cover) {
+ JSKitLib.text($JCL('messagePostFailed'), cover.get("Label"), true);
+ cover.get("Img").src = "//cdn.js-kit.com/images/warning.gif";
+ JSKitLib.show(cover.get("Retry"), "inline");
+ } else {
+ alert($JCL("messagePostFailed"));
+ s.setStateLCF("enable");
+ }
+ }
+ this.postComment(tmpObj, message, {
+ 'onsuccess': onsuccess,
+ 'onerror': onerror
+ });
+}
+
+JSCC.prototype.prepareCommentObj = function(tmpObj) {
+ var cobj = JSKitLib.cloneObject(tmpObj);
+ if(cobj.isEditing) {
+ cobj.Text = cobj.TextEdit;
+ delete cobj.TextEdit;
+ } else if (cobj.echoItem) {
+ cobj.extra = {};
+ cobj.thread = [];
+ } else {
+ this.tmpID++;
+ cobj.ID = "jst-" + this.tmpID;
+ cobj.status = 'A';
+ cobj.profile = this.serverOptions.profile;
+ var avatar = this.avatarsManager.getActiveAvatar();
+ if (avatar) {
+ cobj.avatar = avatar.name;
+ cobj.avatarWidth = avatar.width;
+ cobj.avatarHeight = avatar.height;
+ }
+ cobj.avatarPlaceWidth = this.cmtAvatarPlaceWidth(cobj);
+ cobj.extra = {};
+ cobj.thread = [];
+ cobj.depth = 0;
+ cobj.admin = this.adminMode;
+ var d = new Date();
+ cobj.TS = Math.round(d.valueOf() / 1000) + (this.serverDiffTS || 0);
+ }
+ cobj.jcaIndex = this.jcaIndex;
+ return cobj;
+}
+
+JSCC.prototype.postComment = function(tmpObj, tmpMsg, options) {
+ var s = this;
+ var cmtObj = JSKitLib.cloneObject(tmpObj);
+ if (s.useEcho()) {
+ cmtObj.echoItemFirstTime = true;
+ }
+ if(s.images) cmtObj.imgs = s.images;
+ var msg = JSKitLib.fmap(tmpMsg, function(e){ return e; });
+
+ if(cmtObj.ParentID && !this.objById[cmtObj.ParentID]) {
+ this.invalidateJSPG();
+ if(options && options.onerror) options.onerror();
+ return;
+ }
+
+ cmtObj = this.prepareCommentObj(cmtObj);
+ /* Kick in message submission */
+ msg.push({'Name': 'tid', 'Value': cmtObj.ID});
+ s.prepareImgData(msg);
+ var src = (cmtObj.isEditing ? '.edit' : '.put');
+ var prms = this.getKVListFromMsg(msg);
+ s.commentPostingProcess = {
+ attempts: 1,
+ attemptsMax: 3,
+ cmtObj: cmtObj,
+ start: function(){
+ s.commentPostingProcess.timer = setTimeout(function(){
+ var p = s.commentPostingProcess;
+ if(!p) return;
+ if(p.attempts < p.attemptsMax) {
+ p.attempts++;
+ s.commentPostingProcess.start();
+ } else {
+ if(options && options.onerror)
+ options.onerror();
+ }
+ }, JSCC.REPOST_COMMENT_TIMEOUT);
+ s.setStateLCF("disable");
+ s.server(src, prms, true, {transport: 'POST'});
+ },
+ stop: function(){
+ s.setStateLCF("enable");
+ clearTimeout(s.commentPostingProcess.timer);
+ delete s.commentPostingProcess;
+ if(options && options.onsuccess)
+ options.onsuccess(cmtObj);
+ },
+ disableLCF: function() {
+ var container = s.TC["jsk-CommentFormSurface"];
+ if (!container || cmtObj.isEditing) return;
+ JSKitLib.addClass(container, "js-kit-relative");
+ var p = s.commentPostingProcess;
+ p.enableLCF();
+ p.cover = s.assembleCoverLCF();
+ container.appendChild(p.cover.content);
+ p.adjustCoverPosition(container);
+ },
+ enableLCF: function() {
+ var cover = s.commentPostingProcess.cover;
+ if (cover && cover.content.parentNode) {
+ var container = cover.content.parentNode;
+ container.removeChild(cover.content);
+ JSKitLib.removeClass(container, "js-kit-relative");
+ }
+ },
+ adjustCoverPosition: function(container) {
+ var cover = s.commentPostingProcess.cover;
+ if (JSKitLib.isIE()) {
+ cover.content.style.width = container.offsetWidth+ "px";
+ cover.content.style.height = container.offsetHeight + "px";
+ }
+ cover.get("Msg").style.top = (container.offsetHeight - cover.get("Msg").offsetHeight)/2 + "px";
+ }
+ };
+ s.commentPostingProcess.start();
+}
+
+JSCC.prototype.setStateLCF = function(state) {
+ this.setControlsStateLCF(state, [this.TC['js-Cmtcancel']]);
+ this.commentPostingProcess[state + "LCF"]();
+}
+
+JSCC.prototype.assembleCoverLCF = function() {
+ var s = this;
+ var attachEvent = function(element, extraCallback) {
+ element.href = "javascript:void(0);";
+ element.onclick = function() {
+ s.setStateLCF("enable");
+ delete s.commentPostingProcess;
+ if (extraCallback) extraCallback();
+ return false;
+ };
+ };
+ var descriptors = {
+ "Wrapper": function(element) {
+ JSKitLib.setOpacity(element, 0.7);
+ },
+ "Label": function(element) {
+ var attempts = s.commentPostingProcess.attempts;
+ JSKitLib.text($JCL("posting") + (attempts > 1 ? " (" + $JCL("attempt") + " " + attempts + ")" : "") + "...", element, true);
+ },
+ "Post": function(element) {
+ attachEvent(element, function() {
+ s.CommentSubmitted();
+ });
+ },
+ "Cancel": function(element) {
+ attachEvent(element);
+ }
+ };
+ return JSKitLib.toDOM(s.gtmpl(s.dtPostingCommentDialog), "js-CommentWaitSubmit", descriptors);
+}
+
+JSCC.prototype.getKVListFromMsg = function(msg) {
+ var prms = {};
+ JSKitLib.fmap(msg, function(v) { prms[v.Name] = v.Value; });
+ return prms;
+}
+
+JSCC.prototype.getRatingsAppObject = function() {
+ return this.isStandalone() ? null : $JSKitGlobal.getRatingsAppObject(this.uniq);
+}
+
+JSCC.prototype.hasRatingsAppObject = function() {
+ return this.getRatingsAppObject() ? true : false;
+}
+
+JSCC.prototype.embedRatingsAppObject = function(node) {
+ // One time
+ if ( ! this.embedRatingsAppObjectCompleted) {
+ $JSKitGlobal.copyRatingsAppObject(this.uniq, node);
+ this.embedRatingsAppObjectCompleted = true;
+ }
+}
+
+JSCC.prototype.createMiniStarObject = function(rating, scale) {
+
+ var rao = this.getRatingsAppObject();
+ var fullStar = rao.miniFullStar['user'];
+ var emptyStar = rao.miniEmptyStar['user'];
+ var starWidth = rao.miniStarWidth + 'px';
+ var starHeight = rao.miniStarHeight + 'px';
+
+ var setImage = function(star, imageURL) {
+ if(star.imageURL == imageURL)
+ return; // Already set and we know it
+
+ star.imageURL = imageURL;
+
+ if(document.body.filters) {
+ star.runtimeStyle.filter
+ = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"
+ + imageURL + "', sizingMethod='crop')"
+ } else {
+ star.style.backgroundImage = 'url(' + imageURL + ')';
+ }
+ }
+
+ var obj = document.createElement('div');
+
+ /* Increment by Full Star Ratings */
+ for (var i=2; i <= scale; i += 2) {
+
+ var star = this.cr('div');
+
+ star.style.cssFloat = 'left';
+ star.style.styleFloat = 'left';
+ star.style.width = starWidth;
+ star.style.height = starHeight;
+
+ setImage(star, (rating >= i ? fullStar : emptyStar));
+
+ obj.appendChild(star);
+ }
+
+ return obj;
+}
+
+JSCC.prototype.rerenderName = function(cmt) {
+ var self = this;
+ var ctls = cmt.ctls;
+ var jsc = function(t){return ctls['js-singleComment'+t]};
+ var sn = jsc("Name");
+ if(sn && !(cmt.cobj.msgtype && cmt.cobj.msgtype.match(/T|P/))) {
+ sn.style.cursor = 'pointer';
+ self.appendProfileHandler(sn, cmt.cobj);
+ }
+ var su = jsc("Url");
+ if(su && cmt.cobj.Url && self.serverOptions.extraFieldURL
+ && !(cmt.cobj.msgtype && cmt.cobj.msgtype.match(/T|P/))) {
+ su.style.cursor = 'pointer';
+ su.setAttribute('title', cmt.cobj.Url);
+ su.style.display = 'inline';
+ su.onclick = function() {
+ window.open(cmt.cobj.Url, '_blank');
+ return false;
+ }
+ }
+}
+
+JSCC.prototype.gotPermanentId = function(tmpid, msgId) {
+ var self = this;
+ if (!this.commentPostingProcess) return;
+ var cobj = this.commentPostingProcess.cmtObj;
+ this.commentPostingProcess.stop();
+ cobj.ID = msgId;
+ self.objById[msgId] = cobj;
+ var aux = arguments.length > 2 ? arguments[2] : {};
+ var props = {
+ 'status': cobj,
+ 'Text': cobj,
+ 'originalText': cobj,
+ 'mtext': self.serverOptions,
+ 'mmode': self.serverOptions};
+ for(var pname in props) {
+ if(aux.hasOwnProperty(pname)) {
+ props[pname][pname] = aux[pname];
+ }
+ }
+ if (aux.Text) {
+ JSKW$Events.syncBroadcast('smileys-loadCommentsWidget', cobj, self.jcaIndex);
+ }
+ if(!self.serverOptions.profile && aux.profile) {
+ self.serverOptions.profile = aux.profile;
+ }
+ if (aux.profile) {
+ cobj.profile = aux.profile;
+ }
+ var fillObject = function(obj) {
+ if (aux.avatar) {
+ obj.avatar = aux.avatar;
+ obj.avatarWidth = aux.avatarWidth;
+ obj.avatarHeight = aux.avatarHeight;
+ obj.avatarPlaceWidth = self.cmtAvatarPlaceWidth(obj);
+ }
+ if (aux.destName) {
+ obj.destName = aux.destName;
+ }
+ if (aux.gravatarId) {
+ obj.GravatarID = aux.gravatarId;
+ }
+ return obj;
+ };
+ cobj = fillObject(cobj);
+ var cnvsObj = fillObject({"Name": cobj.Name});
+ if(aux.avatar || aux.gravatarId) {
+ self.placeAvatar(cobj);
+ }
+ if(this.IM && cobj.waitConversation) {
+ cnvsObj.direction = "out";
+ this.conversations[cobj.waitConversation.cnvsIdx] = cnvsObj;
+ cobj.conversation = cobj.waitConversation.cnvsIdx;
+ cobj.waitConversation = false;
+ cobj.hasCnvs = false;
+ }
+ this.isCommentSender = true;
+ this.routeAction(function() {
+ if (!this.isSourceAvailable("Comments")) return;
+ this.cmtInPlace(cobj, function() {
+ if (!this.isCommentSender) return;
+ this.controls.reveal();
+ this.reCalcPages();
+ if (this.useEcho() && this.serverOptions.expandLeaveCmt && !this.config.noautoexpand) {
+ this.ShowCommentDialog(undefined, {nofocus: true});
+ }
+ delete this.isCommentSender;
+ });
+ });
+ this.publishEvent(tmpid == msgId ? 'comment-edited' : 'comment-added', {'cmtId': msgId});
+}
+
+function JSReplyMSGId(tmpid, msgId) {
+ try {
+ var cobj;
+ var widget;
+ for(var i = 0; i < $JCA.length; i++) {
+ var p = $JCA[i].commentPostingProcess;
+ if(p && p.cmtObj && p.cmtObj.ID == tmpid && p.cmtObj.jcaIndex == $JCA[i].jcaIndex) {
+ cobj = p.cmtObj;
+ widget = $JCA[i];
+ break;
+ }
+ }
+ if (widget) widget.gotPermanentId.apply(widget, arguments);
+ } catch(e){}
+}
+
+function JSDeleteMSGId(msgId, jcaIndex, deletedCount) {
+ try {
+ var self = $JCA[jcaIndex];
+ var item = self.jspg.getItemById(msgId);
+ if(item) {
+ var cmt = item.div;
+ if(cmt.cobj.action)
+ JSKW$Events.syncBroadcast("comments_serverRequest_" + cmt.cobj.action);
+ self.routeAction(function() {
+ if(deletedCount>1){
+ this.tag = null;
+ this.invalidateJSPG();
+ var pageNo = this.curPage;
+ this.curPage = 0;
+ this.displayPage(pageNo);
+ } else {
+ this.postHandlerDelete(cmt);
+ }
+ });
+ }
+ } catch(e){}
+}
+
+function JSMarkOffensive() {
+ alert($JCL('markoffMessage'));
+}
+
+function JSCCLike(config) {
+ this.uriAvatar = JSCC.URI_AVATAR;
+ this.uriDomain = JSCC.DOMAIN;
+ this.avatarSize = {"width": "16", "height": "16"};
+ JSKitLib.fmap.call(this, config, function(v, k){ this[k] = v; });
+ this.voters = {"raw": this.voters};
+ this.initVoters();
+ this.loadCSS();
+}
+
+JSCCLike.prototype.loadCSS = function() {
+ JSKitLib.addCss(
+ ".js-kit-like-label { float: left; margin-right: 5px; }" +
+ ".js-kit-like-expand { float: left; cursor: pointer; }" +
+ ".js-kit-like-name { float: left; }" +
+ ".js-kit-like-avatar { float: left; margin-right: 2px; }" +
+ ".js-kit-like-userButton { float: left; height: 16px; margin: 0px 5px 2px 0px; cursor: pointer; }" , "like");
+}
+
+JSCCLike.prototype.label = function(key, data){
+ return this.translator("like_" + key, data);
+}
+
+JSCCLike.prototype.initVoters = function(){
+ var self = this;
+
+ //if voters list contains more than 7 voters - display 5 voters and expand marker
+ this.displayLimit = {"reduced": 5, "full": 7};
+
+ var i = 0;
+ while (i < this.voters["raw"].length){
+ if (this.voters["raw"][i].profile == this.profile()){
+ //if voters list contains your profile we will show it first
+ this.voters["raw"].unshift(this.voters["raw"].splice(i, 1).shift());
+ this.voted = true;
+ break;
+ }
+ i++;
+ }
+ this.guestsCount = 0;
+ this.voters["normalized"] = JSKitLib.filter(function(voter){
+ if (voter.name == "" && voter.profile != self.profile()) self.guestsCount++;
+ return (voter.name != "" || voter.profile == self.profile());
+ }, this.voters["raw"]);
+ if (this.guestsCount > 0) {
+ this.displayLimit["full"]--;
+ this.displayLimit["reduced"]--;
+ }
+ if (this.voters["normalized"].length > this.displayLimit["full"]) {
+ this.voters["reduced"] = this.voters["normalized"].slice(0, this.displayLimit["reduced"]);
+ } else delete(this.voters["reduced"]);
+ this.assemble();
+ this.renderLikeControl();
+}
+
+JSCCLike.prototype.renderLikeControl = function(flag) {
+ var label = this.voted ? "unlike" : "like";
+ JSKitLib.text(this.label(label + (flag ? "_progress" : "")), this.likeControl, true);
+ this.likeControl.title = this.label(label + "_title");
+}
+
+JSCCLike.prototype.sendRequest = function(obj) {
+ var params = {
+ "p": this.path,
+ "id": this.ID,
+ "jx": this.jx,
+ "action": this.voted ? "unlike" : "like"
+ };
+ var request = JSKitLib.foldl(obj, params, function(value, acc, key) { acc[key] = value; });
+ new JSRVC({
+ "uri": this.uriDomain + '/comment-karma',
+ "request": request,
+ "ref": this.ref,
+ "epb": window.JSKitEPB ? JSKitEPB.getAsHash() : {}
+ });
+}
+
+JSCCLike.prototype.vote = function(action, obj) {
+ var voterInList = JSKitLib.lookup(function(voter){
+ return voter.profile == obj.profile;
+ }, this.voters["raw"]);
+
+ if (action == "like" && !voterInList) {
+ this.voters["raw"].unshift(obj);
+ this.initVoters();
+ }
+ if (action == "unlike" && voterInList) {
+ this.voters["raw"] = JSKitLib.filter(function(voter){
+ return voter.profile != obj.profile;
+ }, this.voters["raw"]);
+ this.voted = false;
+ this.initVoters();
+ }
+}
+
+JSCCLike.prototype.assembleVotersList = function(voters) {
+ var self = this;
+ var container = [];
+ var assembleSingleVoter = function(textLabel, avatar){
+ var template =
+ '
';
+ var dom = JSKitLib.toDOM(template, "js-kit-like-", {});
+ self.onVoterRender(dom, {"avatar": avatar});
+ return dom.content;
+ };
+ JSKitLib.fmap(voters || [], function(voter){
+ var avatar = voter.avatar ? {
+ "name": voter.avatar,
+ "width": voter.avatar_width,
+ "height": voter.avatar_height
+ } : undefined;
+ var textLabel = (voter["profile"] == self.profile()) ? self.label("you") : voter["name"];
+ var singleVoter = assembleSingleVoter(textLabel, avatar);
+ self.onVoterInit(singleVoter, {
+ "Name": voter.name,
+ "profile": voter.profile,
+ "avatarData": avatar
+ });
+ container.push(singleVoter);
+ });
+ if (this.guestsCount > 0){
+ var textLabel = self.label((self.guestsCount > 1) ? "guests" : "guest", {"guestsCount": self.guestsCount});
+ container.push(assembleSingleVoter(textLabel));
+ }
+ return container;
+}
+
+JSCCLike.prototype.assemble = function() {
+ var self = this;
+ if (!self.voters["normalized"].length && self.guestsCount == 0) {
+ JSKitLib.removeChildren(self.target);
+ return;
+ }
+
+ var descriptors = [
+ function(container) {
+ container.appendChild(JSKitLib.html('' + self.label("likedBy") + '
'));
+ },
+ function(container){
+ JSKitLib.fmap(self.assembleVotersList(self.voters["reduced"] && !self.expanded ? self.voters["reduced"] : self.voters["normalized"]), function(userButton){
+ container.appendChild(userButton);
+ });
+ },
+ function(container){
+ if (!self.voters["reduced"]) return;
+ self.expandMarker = JSKitLib.html('
');
+ var expandLabel = self.label(self.expanded ? "collapseList" : "andXMore", {"count" : self.voters["normalized"].length - self.displayLimit["reduced"]});
+ JSKitLib.text(expandLabel, self.expandMarker, true);
+ JSKitLib.preventSelect(self.expandMarker);
+ JSKitLib.setEventHandler(self.expandMarker, ["click"], function(){
+ self.expanded = !self.expanded;
+ JSKitLib.removeChildren(self.target);
+ self.assemble();
+ });
+ container.appendChild(self.expandMarker);
+ }
+ ];
+ JSKitLib.removeChildren(self.target);
+ JSKitLib.fmap(descriptors, function(descriptor){
+ descriptor(self.target);
+ });
+ this.onInit();
+}
+
+JSCCLike.prototype.getExpandMarker = function(element){
+ return this.expandMarker;
+}
+
+function JSCCKarma(cObj, self) {
+ var kObj = { p: cObj.karmaP || 0, n: cObj.karmaN || 0 };
+ this.score = kObj.p - kObj.n;
+ this.votes = kObj.p + kObj.n;
+ this.cObj = cObj;
+ this.self = self;
+ this.vote2text();
+ return this;
+}
+JSCCKarma.prototype.vote2text = function() {
+ this.votesText = this.votes + ' '
+ + ((this.votes == 1) ? $JCL("vote") : $JCL("votes"));
+}
+
+JSCCKarma.prototype.recomputeScore = function(scoreAdjustment) {
+ var now = new Date();
+ if(this.votedAlready) {
+ this.score -= this.myVote;
+ } else {
+ this.votes += 1;
+ this.votedAlready = true;
+ var kObj = this;
+ setTimeout(function() {
+ var action = kObj.myVote > 0 ? '+' : '-';
+ kObj.self.server('-karma', {'id': kObj.cObj.ID,
+ 'action': action});
+ }, 2000);
+ }
+ this.score += scoreAdjustment;
+ this.myVote = scoreAdjustment;
+ this.vote2text();
+}
+
+JSCC.prototype.divPages = function(so, items) {
+ var srv = so.pages;
+ this.curPage = 0;
+ var self = this;
+ if(!this.jspg && !this.useEcho()) {
+ this.jspg = new JSPGC(items.length, srv.ps);
+ this.jspg.dataRequest = function(pageIdx, pg, cb) {
+ var pageNo = pageIdx+1;
+ if(!pg.target) pg.target = self.cr('div');
+ var tgt = pg.target;
+ if(tgt.parentNode) tgt.parentNode.removeChild(tgt);
+ self.dataLoader = function() {
+ self.renderLeaveCommentForm();
+ self.curPage = 0;
+ self.displayPage(pageNo, function(immed){ cb.apply(self, [undefined, immed])});
+ }
+ if(srv.pn < 10)
+ srv.pn += 5;
+ self.getpages(pageNo - Math.ceil(srv.pn / 2), {'pn[0]': srv.pn});
+ JSKitLib.text($JCL("loading"), tgt, true);
+ return cb(tgt, false);
+ };
+ this.jspg.dataVisualizator = function(sIdx, arr, pg, cb) {
+ if(!pg.target) pg.target = self.cr('div');
+ var tgt = pg.target;
+ if(tgt.parentNode) tgt.parentNode.removeChild(tgt);
+ var itemsOnPage = arr.length;
+ var cnvs = [];
+ var cn = JSKitLib.fmap(arr,function(V,K){
+ if(!V.html) {
+ var oldN = V.obj.Name;
+ V.obj.Name = (self.IM && V.obj.yours) ? 'Me' : oldN;
+ var oldT = V.obj.Text;
+ if(V.obj.status=='DT') V.obj.Text = 'Deleted';
+ if (V.obj.Url && !V.obj.Url.match(/^https?:\/\//) ) {
+ V.obj.Url = "http://" + V.obj.Url;
+ }
+ V.obj.avatarPlaceWidth = self.cmtAvatarPlaceWidth(V.obj);
+ V.html = self.createCommentAsHTML(V.obj);
+ V.obj.Name = oldN;
+ V.obj.Text = oldT;
+ delete V.div;
+ }
+ V.div = JSKitLib.html(V.html);
+ V.div.id = V.obj.ID;
+ V.obj.hasCnvs = !cnvs[V.obj.conversation];
+ cnvs[V.obj.conversation] = true;
+ self.fixComment(V.div, V.obj, K, K+sIdx, itemsOnPage);
+ return V;
+ });
+ JSKitLib.removeChildren(tgt);
+ self.pageHeader(tgt, sIdx, arr, itemsOnPage);
+ if(self.dtGroupModeration)
+ tgt.appendChild(self.groupModerationBlock(self.dtGroupModeration));
+ for(var i=0; i1) {
+ var crdiv = function(className) {
+ var div = self.cr("div");
+ div.className = className;
+ return div;
+ };
+ var div = crdiv("js-TornPageDivider");
+ var divT = crdiv("js-TornPageDividerTop");
+ var divB = crdiv("js-TornPageDividerBottom");
+ div.appendChild(divT);
+ div.appendChild(divB);
+ tgt.appendChild(div);
+ }
+ }
+ self.pageFooter(tgt, sIdx, arr, itemsOnPage);
+ if(self.dtGroupModeration)
+ tgt.appendChild(self.groupModerationBlock(self.dtGroupModeration));
+ return cb(tgt, true);
+ };
+ }
+ if(!this.jspg && this.useEcho()) {
+ this.jspg = new JSKEchoPGC(srv.ps, srv.echo_after);
+ this.jspg.dataRequest = function(pageIdx, more, echo_after, cb) {
+ var pageNo = pageIdx+1;
+ if(!self.jspg.target) self.jspg.target = self.cr('div');
+ var tgt = self.jspg.target;
+ if(tgt.parentNode) tgt.parentNode.removeChild(tgt);
+ if(!more) JSKitLib.removeChildren(tgt);
+ self.dataLoader = function() {
+ self.renderLeaveCommentForm();
+ self.curPage = 0;
+ self.displayPage(pageNo, function(immed){ cb.apply(self, [undefined, immed])});
+ }
+ var params = {'echo[0]': true};
+ if (more && echo_after) params['echo_after[0]'] = echo_after;
+ self.getpages(undefined, params);
+ var pageNav = self.TC['js-PageNavBottom'];
+ if(pageNav) {
+ JSKitLib.removeChildren(pageNav);
+ pageNav.appendChild(JSKitLib.html(''));
+ }
+ self.jspg.loading = true;
+ return cb(tgt, false);
+ };
+ this.jspg.dataVisualizator = function(arr, cb) {
+ if(!self.jspg.target) self.jspg.target = self.cr('div');
+ var tgt = self.jspg.target;
+ var itemsOnPage = arr.length;
+ var cnvs = [];
+ var cn = JSKitLib.fmap(arr,function(V,K){
+ if(!V.html) {
+ var oldN = V.obj.Name;
+ V.obj.Name = (self.IM && V.obj.yours) ? 'Me' : oldN;
+ var oldT = V.obj.Text;
+ if(V.obj.status=='DT') V.obj.Text = 'Deleted';
+ if (V.obj.Url && !V.obj.Url.match(/^https?:\/\//) ) {
+ V.obj.Url = "http://" + V.obj.Url;
+ }
+
+ if(V.obj.event_publisher) {
+ if(typeof(V.obj.content) == 'string')
+ eval('var content = ' + V.obj.content + '; V.obj.content = content;');
+
+ // Removing links to this page
+ var sanitizer = function(url) {
+ if (!url) return '';
+ if ('/' != url[url.length - 1]) url = url + '/';
+ return url.split('#', 2)[0]
+ .toLowerCase()
+ .replace(/\butm_(source|medium|term|content|campaign)=[^&$]+(&|$)/g, '')
+ .replace(/\?*&*$/, '')
+ .replace(/^https?:\/\/(www\.)?/, '')
+ .replace(/\/\/+/, '/');
+ };
+
+ var el = document.createElement('div');
+ el.innerHTML = V.obj.content.title;
+ var ref = sanitizer(self.config.permalink);
+ var links= JSKitLib.getElementsByClass(el, '*', 'a');
+
+ JSKitLib.fmap(links, function(link) {
+ var data_resolved = sanitizer(link.getAttribute('data-resolved'));
+ var href = sanitizer(link.href);
+ if((href == ref) || (data_resolved == ref))
+ link.parentNode.removeChild(link);
+ });
+
+ var clearText = JSKitLib.trim(el.innerHTML.replace(/<\/?wbr>/g, ''));
+ if (clearText == "") {
+ el.innerHTML = $JCL("sharedThisOn", {"service_name": V.obj.content.service.name || V.obj.event_publisher});
+ }
+
+ V.obj.content.title = el.innerHTML;
+
+ if(V.obj.content.user && (V.obj.content.user.profileUrl || V.obj.content.user.avatarUrl)) {
+ V.obj.avatar = V.obj.GravatarID = (V.obj.content.user.avatarUrl ||
+ V.obj.content.user.profileUrl + "/picture?size=medium");
+ V.obj.avatarWidth = "50";
+ V.obj.avatarHeight = "50";
+ V.obj.avatarPlaceWidth = self.cmtAvatarPlaceWidth(V.obj);
+ V.obj.ProfileURL = V.obj.content.user.profileUrl;
+ }
+ V.html = self.tmpl(self.ffComment, V.obj);
+ } else {
+ V.obj.avatarPlaceWidth = self.cmtAvatarPlaceWidth(V.obj);
+ V.html = self.createCommentAsHTML(V.obj);
+ }
+ V.obj.Name = oldN;
+ V.obj.Text = oldT;
+ V.$olddiv = V.div;
+ V.$isnew = true;
+ V.div = JSKitLib.html(V.html);
+ if (V.obj.extra && V.obj.extra.cssClass) {
+ JSKitLib.addClass(V.div, V.obj.extra.cssClass);
+ }
+ }
+ V.div.id = V.obj.ID;
+ V.obj.hasCnvs = !cnvs[V.obj.conversation];
+ cnvs[V.obj.conversation] = true;
+ if(V.obj.echoItemFirstTime && !V.obj.havingEffect) {
+ V.div.style.overflow = 'hidden';
+ V.div.style.height = "1px";
+ V.obj.height = 1;
+ }
+ if(V.$isnew)
+ self.fixComment(V.div, V.obj, K, K, itemsOnPage);
+ return V;
+ });
+ for(var i=0; i0) {
+ req.variableRequest = idlist.spam;
+ req.request.junk = 'no';
+ req.uri = this.uriDomain + '/comments-junk';
+ new JSRVC(req);
+ }
+ if(idlist.appr.length>0) {
+ req.variableRequest = idlist.appr;
+ req.uri = this.uriDomain + '/comments-approve';
+ new JSRVC(req);
+ }
+ if(idlist.del.length>0) {
+ req.variableRequest = idlist.del;
+ req.request.apr = 'message';
+ req.uri = this.uriDomain + '/comments-del';
+ new JSRVC(req);
+ }
+ break;
+ case 'delete':
+ req.uri = this.uriDomain + '/comments-del';
+ new JSRVC(req);
+ break;
+ case 'spam':
+ req.request.junk = 'yes';
+ req.uri = this.uriDomain + '/comments-junk';
+ new JSRVC(req);
+ break;
+ case 'user':
+ req.request.apr = 'user';
+ req.uri = this.uriDomain + '/comments-del';
+ new JSRVC(req);
+ break;
+ case 'blockuser':
+ req.request.by = 'user';
+ req.uri = this.uriDomain + '/comments-block';
+ new JSRVC(req);
+ break;
+ case 'blockip':
+ req.request.by = 'ip';
+ req.uri = this.uriDomain + '/comments-block';
+ new JSRVC(req);
+ break;
+ case 'unban':
+ if(this.config.permalink) req.request.permalink = this.config.permalink;
+ req.request.unban = 1;
+ req.uri = this.uriDomain + '/comments-approve';
+ new JSRVC(req);
+ break;
+ };
+}
+
+JSCC.prototype.pageHeader = function(target, globalIndex, items, itemsOnPage) {
+ if(this.getSkin()=='smoothgray' && itemsOnPage>0 && items.length>0 && (!this.adminMode || this.inlineModeration)) {
+ var obj = items[0].obj;
+ if(obj.cedge!=3 && obj.cedge!=1) {
+ var div = this.cr("div");
+ div.className = "js-TornPageTop";
+ if(JSKitLib.isIE()) {
+ var img = this.cr("img");
+ img.className = "js-TornPageTopImg";
+ img.src = "//cdn.js-kit.com/images/tornPaperT.gif";
+ div.appendChild(img);
+ }
+ target.appendChild(div);
+ }
+ }
+}
+
+JSCC.prototype.pageFooter = function(target, globalIndex, items, itemsOnPage) {
+ if(this.getSkin()=='smoothgray' && itemsOnPage>0 && items.length==itemsOnPage && (!this.adminMode || this.inlineModeration)) {
+ var obj = items[itemsOnPage-1].obj;
+ if(obj.cedge!=3 && obj.cedge!=2) {
+ var div = this.cr("div");
+ div.className = "js-TornPageBottom";
+ if(JSKitLib.isIE()) {
+ var img = this.cr("img");
+ img.className = "js-TornPageBottomImg";
+ img.src = "//cdn.js-kit.com/images/tornPaperB.gif";
+ div.appendChild(img);
+ }
+ target.appendChild(div);
+ }
+ }
+}
+
+JSCC.prototype.htmlPaginate = function(thread) {
+ return this.htmlPaginator(thread, []);
+}
+
+JSCC.prototype.htmlPaginator = function(thread, arr) {
+ var tl = thread.length;
+ for(var i = 0; i < tl; i++) {
+ var obj = thread[i];
+ var present = (obj.status == 'D') ? 0 : 1;
+ if(present) {
+ arr.push(obj);
+ }
+ this.htmlPaginator(obj.thread, arr);
+ }
+ return arr;
+}
+
+JSCC.prototype.restoreEchoAfter = function() {
+ if(this.useEcho()) {
+ this.jspg.echo_after = this.jspg.$old_echo_after;
+ }
+}
+
+JSCC.prototype.invalidateJSPG = function() {
+ this.restoreEchoAfter();
+ this.jspg.invalidate();
+}
+
+// Part of externally useable API
+JSCC.prototype.rerender = function() {
+ var pageToDisplay = this.curPage;
+ this.restoreEchoAfter();
+ this.curPage = 0;
+ this.jspg.invalidatePagesView(pageToDisplay-1, 1);
+ this.displayPage(pageToDisplay);
+}
+
+JSCC.prototype.setPath = function(path) {
+ this.pathOverride = path;
+}
+
+JSCC.prototype.detectCommentDialogOpened = function() {
+ var ccd = this.TC[this.forMsg && this.forMsg.isEditing ? "js-EditComment" : "js-CreateComment"];
+ return !!ccd && JSKitLib.hasParentNode(ccd) && ccd.style.display == 'block';
+}
+
+JSCC.prototype.displayPage = function(pageNo, cb) {
+ if(this.loading && !cb) {
+ var nt = (new Date()).valueOf();
+ if((nt - this.loading) > 5000) {
+ this.gen++;
+ } else {
+ return;
+ }
+ }
+
+ if(pageNo < 1)
+ return;
+
+ if(pageNo > this.jspg.pageCount)
+ pageNo = this.jspg.pageCount;
+
+ var immediate = true;
+
+ if(this.curPage != pageNo) {
+ var cd = this.detectCommentDialogOpened();
+ try {
+ if (!this.useEcho() || this.forMsg) this.CommentCancelled();
+ } catch(e) { }
+
+ if(!this.useEcho())
+ try {
+ if(this.curPage) {
+ var p = this.jspg.getPage(this.curPage - 1);
+ if(p && p.target && p.target.parentNode)
+ p.target.parentNode.removeChild(p.target);
+ }
+ } catch(e) { }
+ var oc = this.TC["js-OldComments"];
+ var self = this;
+ if(this.useEcho()) {
+ this.curPage = 1;
+ var pcb = function(p, immed) {
+ if(p) {
+ if(self.jspg.target && !JSKitLib.hasParentNode(self.jspg.target)) oc.appendChild(p);
+ p.style.display = '';
+ }
+ if(immed && cb) cb.apply(self, [immed]);
+ };
+ this.jspg.getPageVisualization(pageNo-1, pcb);
+ if(cd && this.replyForId) {
+ var parentMsg = this.jspg.getItemById(this.replyForId);
+ this.ShowCommentDialog(parentMsg ? this.replyForId : undefined);
+ }
+ cd = undefined;
+ } else {
+ this.curPage = pageNo;
+ var pcb = function(p, immed) {
+ if(p) {
+ oc.appendChild(p);
+ p.style.display = '';
+ }
+ if(immed && cb) cb.apply(self, [immed]);
+ };
+ this.jspg.getPageVisualization(pageNo-1, pcb);
+ }
+ immediate = false;
+ if (cd && !this.forMsg) { // show only if not reply and not editing
+ if (((this.config.nolc && this.IM == 'foreign') || (this.serverOptions.expandLeaveCmt && !this.config.noautoexpand)) && !this.config.moderate) {
+ this.ShowCommentDialog(undefined, {nofocus: true});
+ }
+ }
+ }
+
+ var ocw = this.TC["js-OldCommentsWrap"];
+ if (this.jspg.itemsCount != 0)
+ {
+ JSKitLib.show(ocw);
+ }
+ else
+ {
+ JSKitLib.hide(ocw);
+ }
+
+ if(!this.jspg.loading || !this.useEcho()) this.rePageNavigator(this.curPage-1);
+ if(immediate && cb) cb.apply(this, [immediate]);
+}
+
+JSCC.prototype.SearchLine = function() {
+ var self = this;
+ var sExit = self.cr('span');
+ var title = self.cr('span');
+ title.className = 'js-SearchTitle';
+ title.innerHTML = ''+$JCL("youSearchedFor")+': ';
+ sExit.appendChild(title);
+ var line = self.cr('span');
+ line.className = 'js-SearchWords';
+ text = JSKitLib.truncate(self.searchString, 15, "...", true);
+ line.insertBefore(JSKitLib.text(text),line.firstChild);
+ sExit.appendChild(line);
+ var del = self.cr('input');
+ del.type = 'button';
+ del.value = $JCL('clearSearch');
+ sExit.appendChild(del);
+ var obj={
+ 'containerElement': sExit,
+ 'field': line,
+ 'itemObject': self,
+ 'type': 'Search',
+ 'Property': 'searchString',
+ 'title': $JCL("youSearchedFor")+': ',
+ 'mode': 'full'
+ };
+ obj.jsipe$start = function(){
+ del.style.display = "none";
+ line.style.border = "0px";
+ title.style.display = "none";
+ return true;
+ }
+ obj.jsk$on_submit_exit = function(value){
+ self.searchString = value;
+ self.viewControl({name: "search"});
+ }
+ line.wasEdited = function(value){
+ JSKitLib.text(JSKitLib.truncate(value, 15, "...", true), line, true);
+ del.style.display = "";
+ line.style.borderBottom = "";
+ title.style.display = "";
+ }
+ del.onclick = function(){
+ this.name="del-line";
+ self.viewControl(this);
+ }
+ var jsipe = new JSIPE(obj);
+ return sExit;
+}
+
+JSCC.prototype.navSym = { "prev": "←", "next": "→" };
+
+JSCC.prototype.rePageNavigator = function(pageIdx) {
+ var s = this;
+ var hasMultiplePages = s.jspg.pageCount > 1 || s.jspg.echo_after;
+ var display = s.searchString || hasMultiplePages ? "" : "none";
+ var assemblePageNavigation = function() {
+ var navigation = '';
+ if (hasMultiplePages) {
+ navigation = s.useEcho()
+ ? s.pageNavigatorEchoLive(s.jspg.pageCount, s.jspg.echo_after)
+ : s.getSkin() == "echo"
+ ? s.pageNavigatorEcho(s.jspg.pageCount, s.curPage)
+ : s.pageNavigator(s.jspg.pageCount, s.curPage);
+ }
+ return (typeof(navigation) == "string")
+ ? JSKitLib.html('' + (navigation || '') + '
')
+ : navigation;
+ };
+ var nvs = s.useEcho() ? ['Bottom'] : ['Top','Bottom'];
+ for(var i = 0; i < nvs.length; i++) {
+ var bar = s.TC['js-PageNav' + nvs[i]];
+ if (!bar) continue;
+ JSKitLib.replaceChildren(bar, assemblePageNavigation());
+ JSKitLib.preventSelect(bar);
+ bar.style.display = display;
+ if(i) bar.style.display = ((pageIdx==undefined) ? 'none' : '');
+ if(s.searchString) s.addChild(bar, s.SearchLine(), true);
+ }
+}
+
+JSCC.prototype.pageNavigator = function(pages, cur) {
+ var self = this;
+ var arr = [];
+ var postingProcessValidation = "if ($JCA["+self.jcaIndex+"].commentPostingProcess) { alert($JCL('messagePostingInProgress')); return false; }";
+ var f = function(i, txt, cmt, cls, cf) {
+ return '' + txt + ' '; }
+ arr.push($JCL('page'));
+ arr.push(f(cur - 1, this.navSym.prev, $JCL('pagePrevious'),
+ 'js-PageArrow' + ((cur == 1)?' js-PageArrowCur':'')));
+ for(var i = 1; i <= pages; i++) {
+ if((i == 4 || i == 3) && (cur - i) > 3) {
+ i = Math.floor((cur - i) / 2 + i);
+ arr.push(f(i, '…', 'Page-' + i));
+ i = cur - ((pages - cur > 3 || cur == pages) ? 2 : 1);
+ }
+ if((i == cur + 3) && (pages - cur) > 4) {
+ i = Math.floor((pages - cur) / 2 + cur);
+ arr.push(f(i, '…', 'Page-' + i));
+ i = pages - 1;
+ }
+ if(i == cur) {
+ arr.push(f(i, i, 'Page-' + i, "js-PageNCur", '$JCA['+self.jcaIndex+'].jspg.invalidate(); $JCA['+self.jcaIndex+'].rerender();'));
+ } else {
+ arr.push(f(i, i, 'Page-' + i));
+ }
+ }
+ arr.push(f(cur + 1, this.navSym.next, $JCL('pageNext'),
+ 'js-PageArrow' + ((pages == cur)?' js-PageArrowCur':'')));
+ return arr.join('');
+}
+
+JSCC.prototype.pageNavigatorEcho = function(pages, cur) {
+ var self = this;
+ var assemble = function(container, i, txt, cmt, cls, cf) {
+ var isInactive = function(cls) {
+ return cls && cls.match(/PrevOff|NextOff|Active/);
+ };
+ var template =
+ '' +
+ (isInactive(cls) ? txt : '' + txt + ' ') +
+ ' ';
+ var scroll = function() {
+ var anchor = self.TC['jsk-HeaderWrapper'];
+ if (!anchor || JSKitLib.getStyleProperty(anchor, 'display') == 'none') {
+ anchor = self.TC['jsk-ThreadWrapper'];
+ }
+ if (anchor) anchor.scrollIntoView(true);
+ };
+ var linkHandler = function(element) {
+ element.href = "#" + cmt;
+ element.onclick = function() {
+ if (self.commentPostingProcess) {
+ alert($JCL('messagePostingInProgress'));
+ return false;
+ }
+ if (cf) {
+ cf();
+ return false;
+ }
+ self.displayPage(i, function() {
+ self.hideExpirationBanner();
+ setTimeout(scroll, 0);
+ });
+ return false;
+ };
+ JSKitLib.setMouseEvent(element, "over", function() {
+ window.status = cmt;
+ });
+ JSKitLib.setMouseEvent(element, "out", function() {
+ window.status = '';
+ });
+ };
+ container.appendChild(JSKitLib.toDOM(template, "js-Page",
+ {"Link": linkHandler}).content);
+ }
+ var template =
+ '';
+ var assemblePages = function(element) {
+ assemble(element, cur - 1, $JCL('btnPagePrevious'), $JCL('pagePrevious'),
+ ((cur == 1) ? 'jsk-PrevOff' : 'jsk-Prev'));
+ for(var i = 1; i <= pages; i++) {
+ if((i == 4 || i == 3) && (cur - i) > 3) {
+ i = Math.floor((cur - i) / 2 + i);
+ assemble(element, i, '…', 'Page-' + i);
+ i = cur - ((pages - cur > 3 || cur == pages) ? 2 : 1);
+ }
+ if((i == cur + 3) && (pages - cur) > 4) {
+ i = Math.floor((pages - cur) / 2 + cur);
+ assemble(element, i, '…', 'Page-' + i);
+ i = pages - 1;
+ }
+ if(i == cur) {
+ var cb = function() {
+ self.jspg.invalidate();
+ self.rerender();
+ };
+ assemble(element, i, i, 'Page-' + i, 'jsk-Active', cb);
+ } else {
+ assemble(element, i, i, 'Page-' + i);
+ }
+ }
+ assemble(element, cur + 1, $JCL('btnPageNext'), $JCL('pageNext'),
+ ((pages == cur) ? 'jsk-NextOff' : 'jsk-Next'));
+ };
+ return JSKitLib.toDOM(template, "jsk-", {"Pager": assemblePages}).content;
+}
+
+JSCC.prototype.pageNavigatorEchoLive = function(pages, cur) {
+ var self = this;
+ var template =
+ '' +
+ '{Label:More} ' +
+ '
';
+ var moreButtonHandler = function(element) {
+ element.onclick = function() {
+ self.displayPage(2);
+ };
+ JSKitLib.setMouseEvent(element, "over", function() {
+ JSKitLib.addClass(element, "jsk-PagerItemHover");
+ });
+ JSKitLib.setMouseEvent(element, "out", function() {
+ JSKitLib.removeClass(element, "jsk-PagerItemHover");
+ });
+ };
+ return JSKitLib.toDOM(this.gtmpl(template), "js-Page", {"More": moreButtonHandler}).content;
+}
+
+JSCC.prototype.hideSettingsWindow = function(wname) {
+ if(this[wname]) this.settingsWindow(wname);
+}
+
+JSCC.prototype.showProgress = function(wname, on) {
+ if(this[wname]) this[wname].showProgress(on);
+}
+
+JSCC.prototype.settingsWindow = function(wname, atDiv, html) {
+ var s = this;
+ if(s[wname]) {
+ if(!s.sWHideable) return;
+ s[wname].parentNode.removeChild(s[wname]);
+ delete s[wname];
+ return;
+ }
+ var nohide = function() {
+ s.sWHideable = false;
+ if(s.swsHidt) clearTimeout(s.swsHidt);
+ s.swsHidt = setTimeout(function(){s.sWHideable=true}, 100);
+ }
+ var div = this.cr("div");
+ div.className = "js-SettingsWindow";
+ if (s.config.nolc) JSKitLib.addClass(div, "js-SettingsWindowNolc");
+ div.style.background = '#FFFFFF url('+this.uriDomain
+ +'/images/bg-header-gray.png) bottom repeat-x';
+ div.onclick = nohide;
+ div.onselectstart = function() { return false; }
+ if(typeof(html) == 'string') {
+ div.innerHTML = html;
+ } else {
+ if(!html.dropWidth) div.style.width = '20em';
+ div.appendChild(html);
+ }
+
+ if (wname == 'ctWnd' && s.TC['js-WelcomePanel']) {
+ var aoh = s.cr('div');
+ aoh.className = 'js-SettingsWindowHeader';
+ JSKitLib.text($JCL('administratorOptions'), aoh);
+ div.appendChild(aoh);
+ var wp = s.TC['js-WelcomePanel'];
+ var links = JSKitLib.html(''
+ + '');
+ var tc = JSKitLib.mapClass2Object({}, links);
+ div.appendChild(links);
+ tc['js-WelcomeOpenPanel'].onclick = function() {
+ JSKitLib.toggle(wp);
+ JSKitLib.text($JCL(JSKitLib.visible(wp) ? 'closeWelcome' : 'openWelcome'), this.lastChild.lastChild);
+ };
+ tc['js-WelcomeContact'].onclick = function(){location.href = s.uriDomain + '/comments/qa.html';};
+ }
+
+ var pgr = this.cr('div');
+ pgr.className = "js-Progress";
+ var url = this.uriDomain + '/images/progress-wg.png';
+ if(document.body.filters) {
+ pgr.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=" + url + ", sizingMethod=crop)";
+ } else pgr.style.backgroundImage = 'url(' + url + ')';
+ div.appendChild(pgr);
+ div.showProgress = function(on) {
+ if(!on) {
+ if(div.pIntvl) clearInterval(div.pIntvl);
+ div.pIntvl = null;
+ pgr.style.visibility = 'hidden';
+ return;
+ } else if(div.pIntvl) return;
+ var f = function() {
+ pgr.vison = !pgr.vison;
+ pgr.style.visibility = pgr.vison
+ ? 'visible' : 'hidden';
+ }
+ f();
+ div.pIntvl = setInterval(f, 500);
+ }
+
+ s[wname] = div;
+ var swh = this.cr("div");
+ swh.className = "js-SettingsWindowHeader";
+ JSKitLib.text($JCL(wname == 'ctWnd' ? "viewOptions" : "moderation"), swh);
+ div.insertBefore(swh, div.firstChild);
+ div.style.position = "absolute";
+
+ var jsd = new JSDL(div, [swh]);
+ document.body.appendChild(div);
+ div.style.left = jsd.getElmAbsPos(atDiv, false).x + "px";
+ div.style.top = jsd.getElmAbsPos(atDiv, false).y + atDiv.offsetHeight + "px";
+
+ try {
+ if (document.body.clientWidth < jsd.getElmAbsPos(atDiv, false).x + div.offsetWidth)
+ div.style.left = document.body.clientWidth - div.offsetWidth -
+ (parseInt(div.style.marginLeft) || 0) -
+ (parseInt(div.style.marginRight) || 0) + "px";
+ } catch(e) {;}
+
+ var ifrWr;
+ if(JSKitLib.getBrowser() == 'gecko' && !atDiv.notShowIfr) {
+ ifrWr = this.cr("div");
+ ifrWr.id = "jsk-yIfr";
+ var yIfr = this.cr("iframe");
+ yIfr.style.position = "absolute";
+ yIfr.style.top = 0;
+ yIfr.style.left = 0;
+ yIfr.style.zIndex = -1;
+ yIfr.style.display = "block";
+ yIfr.style.height = div.offsetHeight + "px";
+ yIfr.style.width = div.offsetWidth + "px";
+ yIfr.scrolling = "no";
+ yIfr.frameBorder = "0";
+ ifrWr.appendChild(yIfr);
+ div.appendChild(ifrWr);
+ }
+ div.jsk$on_start_drag = function(){if(ifrWr) ifrWr.style.display = "none"};
+ div.jsk$on_stop_drag = function(){if(ifrWr) ifrWr.style.display = ""};
+ nohide();
+}
+
+JSCC.prototype.getImages = function(id) {
+ var arg = {rnd: id, jx: this.jcaIndex};
+ this.server(this.uriDomain + '/api/images/pick-attachments.js', arg);
+}
+
+JSCC.prototype.prepareImgData = function(msg) {
+ if(this.images){
+ JSKitLib.removeChildren(this.imgArea);
+ JSKitLib.map(function(elem, i){
+ JSKitLib.fmap(['img','orig','width','height','descr','mime'],
+ function(E) { msg.push({'Name': 'js-CmtattachFile_'+i+'_'+E, 'Value': elem[E]})}
+ );
+ },this.images);
+ }
+}
+
+JSCC.prototype.parseImgData = function(obj) {
+ var re = /attachFile_(\d+)_(\w+)/;
+ var imgs = [];
+ for (var i in obj){
+ var keys = re.exec(i);
+ if (keys) {
+ if (!imgs[keys[1]]) imgs[keys[1]] = {};
+ imgs[keys[1]][keys[2]] = obj[i];
+ }
+ }
+ return imgs;
+}
+
+JSCC.prototype.createImages = function(imgs, isPreview){
+ var s = this;
+ var d=function(){return s.div.apply(s,arguments);}
+
+ var content = isPreview ? d() :
+ d("js-all-previewImages",d("js-previewImageTitle jsk-ItemAttachmentsTitle jsk-SecondaryBackgroundColor", $JCL('picTitle')),
+ JSKitLib.html('
'));
+
+ var bloburl = function(name) {
+ return name.match(/^[^\/]+$/)?(s.uriDomain+"/blob/"+name):"";
+ }
+
+ var crImg = function(elem, i){
+ var img = d("js-previewImage jsk-ItemAttachmentWrapper");
+ var thumb = s.cr("img");
+ elem.descr = elem.descr || '';
+ thumb.src = bloburl(elem.img);
+ JSKitLib.setStyle(thumb, " width: "+elem.width+"px; height: "+elem.height+"px; cursor: pointer;");
+ JSKitLib.addClass(thumb, "jsk-ItemAttachmentIcon");
+ var wrap = d("js-imageWrap jsk-ItemAttachmentIconWrapper");
+ JSKitLib.setStyle(wrap, "margin-top: " + ((96-elem.height)/2) + "px; margin-bottom: " + ((96-elem.height)/2) + "px;");
+ thumb.onclick = function() { window.open(bloburl(elem.orig)); }
+ var text = d("js-previewImageDescr jsk-ItemAttachmentLabel");
+ s.addChild(wrap, thumb);
+ s.addChild(img, wrap);
+ if (isPreview) {
+ var wasEdited = function(){
+ if(elem.descr != "" ) JSKitLib.removeClass(text,"js-uploadGreyDescr");
+ else JSKitLib.addClass(text,"js-uploadGreyDescr");
+ }
+ var jsipe = new JSIPE2({obj: elem,
+ property: 'descr',
+ title: 'Description',
+ defaultText: 'Add caption',
+ width: '90px',
+ maxLength: 80,
+ hideApplyBtn: true,
+ jsk$wasEdited: wasEdited
+ });
+ text.appendChild(jsipe.div);
+ var onEditBtnClick = function(e){
+ if(jsipe.editMode) jsipe.editMode(e);
+ JSKitLib.stopEventPropagation(e || window.event);
+ }
+ var onDeleteBtnClick = function(e){
+ img.parentNode.removeChild(img);
+ if(imgs && imgs[i]) imgs.splice(i, 1);
+ JSKitLib.stopEventPropagation(e || window.event);
+ }
+ var editBtn = s.crImgCtrl("edit", {top: "60px", left: "15px"}, onEditBtnClick);
+ var deleteBtn = s.crImgCtrl("delete", {top: "60px", left: "57px"}, onDeleteBtnClick);
+ var displayMode = function(mode){
+ editBtn.style.display = mode;
+ deleteBtn.style.display = mode;
+ }
+ img.onmouseover = function(e) { displayMode("inline"); }
+ img.onmouseout = function(e) { displayMode("none"); }
+ s.addChild(img, editBtn);
+ s.addChild(img, deleteBtn);
+ if(elem.descr == "") JSKitLib.addClass(text,"js-uploadGreyDescr");
+ } else {
+ text.innerHTML = elem.descr.replace(//g,">");
+ }
+ thumb.title = JSKitLib.htmlUnquote(elem.descr);
+ s.addChild(img, text);
+ s.addChild(content, img);
+ }
+ JSKitLib.map(crImg,imgs);
+ s.addChild(content, JSKitLib.html('
'));
+
+ return content;
+}
+
+JSCC.prototype.crImgCtrl = function(type, position, onClick) {
+ var btn = this.cr("div");
+ var ctrlBtn = { width : "30px", height : "30px", imgWidth : "30px", imgHeight : "30px" };
+ JSKitLib.setStyle(btn, "display:none; background:transparent; position:absolute; float:left; padding:0; margin:0; "
+ + "width:" + ctrlBtn.width + "; height:" + ctrlBtn.height + "; cursor: pointer;"
+ + "top:" + position.top + "; left:" + position.left);
+ btn.title = $JCL(type + "Image");
+ btn.onclick = onClick;
+ imgUrl = this.uriDomain + "/images/" + "avatar-" + type + ".png";
+ JSKitLib.addPNG(btn, imgUrl);
+
+ return btn;
+}
+
+
+JSCC.prototype.addImage = function(img) {
+ if(this.lbliChange) this.lbliChange(0);
+ if (typeof(img) == "object"){
+ if (img.error) {
+ switch (img.error) {
+ case 'big_image':
+ alert($JCL('imgUploadErrorBigImage'));
+ break;
+ case 'wrong_format':
+ alert($JCL('imgUploadErrorWrongFormat'));
+ break;
+ case 'internal_error':
+ default:
+ alert($JCL('imgUploadErrorInternal'));
+ }
+ return;
+ }
+ if (this.images) this.images.push(img)
+ else this.images = [img];
+ if (!this.imgArea) return;
+ JSKitLib.removeChildren(this.imgArea);
+ var content = this.createImages(this.images, true);
+ this.addChild(this.imgArea, content);
+ }
+}
+
+JSCC.prototype.viewControl = function(sel) {
+ var s = this;
+ var ap = { "usr": "yes" };
+ switch(sel.name) {
+ case "jss-srt":
+ var newSortBy = sel.options[sel.selectedIndex].value;
+ if(newSortBy == s.config.sort) return true;
+ s.config.sort = newSortBy;
+ s.showProgress('ctWnd', true);
+ break;
+ case "jss-rev":
+ var backwardsNewStatus = sel.selectedIndex?'yes':'no';
+ if(s.config.backwards == backwardsNewStatus) return true;
+ s.config.backwards = backwardsNewStatus;
+ s.showProgress('ctWnd', true);
+ break;
+ case "jss-prs":
+ var newThr = sel.options[sel.selectedIndex].value == 'flat' ? 'no' : 'yes';
+ if(newThr == s.config.thread) return true;
+ s.config.thread = newThr;
+ s.showProgress('ctWnd', true);
+ break;
+ case "search":
+ ap.srch = s.searchString;
+ break;
+ case "del-line":
+ break;
+ default: return false;
+ }
+ s.dataLoader = function() {
+ this.showProgress('ctWnd', false);
+ this.curPage = 0;
+ this.displayPage(1); }
+ if(this.curPage) {
+ var p = this.jspg.getPage(this.curPage - 1);
+ if(p && p.target && p.target.parentNode)
+ p.target.parentNode.removeChild(p.target);
+ }
+ s.ctag = null;
+ ap.opts = s.config.sort+'|'+(s.config.backwards == "yes" ? "desc" : "asc")+'|'+(s.config.thread == "yes" ? "thr" : "flat");
+ s.getpages(0, ap);
+ return true;
+}
+
+JSCC.prototype.placeAvatar = function(obj, div) {
+ div = div || obj.avatarPlace;
+ if(!div) return;
+
+ if(this.getSkin() != 'echo' && !obj.avatar && !obj.GravatarID) {
+ obj.avatarPlace = div;
+ return;
+ }
+ var container = {
+ "instance": div,
+ "width": obj.avatarPlaceWidth,
+ "height": obj.avatarPlaceWidth
+ };
+ this.appendAvatarImage(container, obj);
+ this.appendProfileHandler(div, obj);
+ return div;
+}
+
+JSCC.prototype.appendAvatarImage = function(container, obj) {
+ var self = this;
+ obj = obj || {};
+ var avtCtrl = this.avatarsManager;
+ var data = obj.avatar ?
+ {"name": obj.avatar, "width": obj.avatarWidth, "height": obj.avatarHeight} :
+ avtCtrl.anonymousAvatarData();
+
+ var avatar = avtCtrl.calcAvatarDim(container, data);
+ avatar.name = obj.GravatarID ?
+ avtCtrl.getGravatarURL(obj.GravatarID, this.maxAvatarDims) :
+ avtCtrl.avatarURL(avatar.name);
+ avatar.onerror = function() {
+ this.onerror = null;
+ self.appendAvatarImage(container);
+ }
+ avtCtrl.assembleAvatar(container, avatar);
+}
+
+JSCC.prototype.placeProcessAvatar = function(div) {
+ if(!div) return;
+ JSKitLib.removeChildren(div);
+ JSKitLib.addPNG(div, '//cdn.js-kit.com/images/progress-wg.png');
+ JSKitLib.addStyle(div, "width: 15px; height: 15px;");
+}
+
+JSCC.prototype.refreshComments = function(params) {
+ var s = this;
+ params = params || {};
+ s.deleteWelcomePanel();
+ s.hideExpirationBanner();
+ s.invalidateJSPG();
+ s.objById = {};
+ if (s.curPage == 1) s.curPage = 0;
+ s.displayPage(1, function() {
+ if (!s.isSourceAvailable("Comments")) return;
+ s.preventAnonymousComments();
+ s.makeWelcomePanel();
+ s.ShowCommentDialog(s.replyForId, params);
+ });
+}
+
+JSCC.prototype.preventAnonymousComments = function() {
+ var anonymCond = this.anonymousCmt && !this.jskauth.isLogged();
+ this.setControlsStateLCF(anonymCond ? "disable" : "enable");
+}
+
+JSCC.prototype.setControlsStateLCF = function(state, extraControls) {
+ var s = this;
+ var disable = state == "disable";
+ var disableCtrls = JSKitLib.merge([s.TC['js-CmtText'], s.TC['js-CmtTextEdit'], s.TC['js-Cmtsubmit'], s.TC['js-CmtsubmitEdit'], s.TC['js-CmtcancelEdit'], s.TC['js-CmtName'], s.TC['js-CmtEmail'], s.imgUpload], extraControls || []);
+ var lockCtrls = [s.TC['js-Cmtsubmit']];
+ var imgArea = s.TC['js-commentImageArea'];
+
+ JSKitLib.fmap(disableCtrls, function(V){ if (V) V.disabled = disable; });
+ JSKitLib.fmap(lockCtrls, function(V){ if (V) V.btnLocked = (disable) ? "true" : null; });
+ if (imgArea) imgArea.disableUpload = disable;
+}
+
+JSCC.prototype.setThirdPartyShare = function() {
+ var s = this;
+ var po = s.TC["js-commentPubOptions"];
+ if(!po) return;
+ JSKitLib.removeChildren(po);
+ var appendSharingControl = function(type, extraElement) {
+ var identity = s.jskauth.getAuthIdentity(type);
+ var publish = identity && identity.publish;
+ var control = JSKitLib.html('');
+ control.defaultChecked = !!publish;
+ control.checked = !!publish;
+ control.value = control.checked ? "on" : "off";
+ control.onchange = function() {
+ this.value = this.checked ? "on" : "off";
+ };
+ var label = JSKitLib.html('');
+ po.appendChild(control);
+ po.appendChild(label);
+ if (extraElement) po.appendChild(extraElement);
+ };
+ JSKitLib.fmap(s.jskauth.getIdentities("auth"), function(identity) {
+ if (identity.can_publish && identity.user) {
+ var extraElement = (identity.type == "yahoo") ? JSKitLib.html('') : undefined;
+ appendSharingControl(identity.type, extraElement);
+ }
+ });
+}
+
+JSCC.prototype.wrapJSKAuth = function() {
+ var s = this;
+ var tc = s.TC;
+ var appendAuthSelector = !tc["js-kit-lcf-userInfoWrapper"];
+
+ if (s.config.nolc) return;
+ if (!tc['js-AuthAreaWrap']) {
+ var items = ['js-commentOpenID', 'js-commentInputOpenID', 'js-CmtOpenID', 'js-OpenIDError'];
+ JSKitLib.fmap(items, function(item) {
+ if (tc[item]) tc[item].parentNode.removeChild(tc[item]);
+ });
+ if (appendAuthSelector) return;
+ }
+
+ var authAreaTmpl =
+ '' +
+ '' +
+ '
' +
+ '
' +
+ '
[] ' +
+ '
' +
+ '
';
+
+ if (tc['js-commentInputOpenID']) JSKitLib.hide(tc['js-commentInputOpenID']);
+
+ if (appendAuthSelector) {
+ var authAreaContainer = JSKitLib.html(s.gtmpl(authAreaTmpl));
+ tc['js-AuthAreaWrap'].appendChild(authAreaContainer);
+ JSKitLib.mapClass2Object(tc, authAreaContainer);
+ }
+}
+
+JSCC.prototype.initAvatarsManager = function(size) {
+ var s = this;
+ var so = s.serverOptions;
+ if (s.avatarsManager) s.avatarsManager.deActivateEvents();
+ var identities = JSKitLib.foldl({}, s.jskauth.identities.auth, function(identity, acc) {
+ if (identity.group != "third_party") return;
+ acc[identity.type] = {
+ "title": s.jskauth.getIdentityLabel(identity.type, true),
+ "action": identity.user ? null : function() {
+ s.jskauth.show(identity.type);
+ },
+ "authenticated": !!identity.user
+ };
+ });
+ var avatars = so.avatars || [];
+ var addEPBAvatar = function(identity) {
+ if (JSKitEPB.isExists() && identity) {
+ var type = 'http://' + s.config.domain;
+ var index = -1;
+ JSKitLib.fmap(avatars, function(av, i) {
+ if (av.type == type) {
+ index = i;
+ }
+ });
+ var avatar = JSKitEPB.getValue('Avatar');
+ if (avatar) {
+ if (index < 0) {
+ JSKitLib.fmap(avatars, function(av) { delete av.chosen; });
+ avatars.push({name: avatar, width: 64, height: 64, type: type, params: identity.params, chosen: true});
+ } else {
+ avatars[index].name = avatar;
+ }
+ } else if (index >= 0) {
+ avatars.splice(index, 1);
+ }
+ }
+ }
+ addEPBAvatar(s.jskauth.getAuthIdentity('epb'));
+
+ var config = {
+ "id": "comments-" + s.jcaIndex,
+ "ref": JSKitLib.getRef(s),
+ "size": size,
+ "yours": !s.config.nolc,
+ "layer": s.getSkin() == "smoothgray" ? this.target : undefined,
+ "target": this.target,
+ "labels": $JCL,
+ "avatars": avatars,
+ "autoSave": false,
+ "controls": [s.TC["js-Cmtsubmit"]],
+ "uriAvatar": s.uriAvatar,
+ "identities": identities,
+ "gravatarEmail": so.gravatarEmail
+ };
+ return new JSKAvatars(config);
+}
+
+JSCC.prototype.setFormFields = function(fields) {
+ var s = this;
+ var tc = s.TC;
+ var emptyLabels = {
+ 'Url': $JCL('urlIsOptional'),
+ 'Email': $JCL('emailIsOptional')
+ }
+
+ JSKitLib.fmap(fields, function(v, name) {
+ var o = tc['js-Cmt'+name];
+ if(o) {
+ o.jsk$setdfl = function(val) {
+ o.style.color = '';
+ o.jsk$setdfl = false;
+ o.jsk$not_specified = false;
+ o.value = val || '';
+ }
+ if (v) {
+ o.jsk$setdfl(v);
+ } else {
+ o.style.color = '#808080';
+ o.value = emptyLabels[name];
+ o.jsk$not_specified = true;
+ }
+ o.onfocus = function() { if (o.jsk$setdfl) o.jsk$setdfl(); }
+ }
+ });
+}
+
+JSCC.prototype.getThreadHeader = function() {
+ var s = this;
+ var header;
+ if (s.config.skin == 'echo') {
+ var replacements = {
+ "Title": s.config["thread-title"],
+ "CountLabel": $JCL("commentsCountLabel", {"Count": s.serverOptions.pages.tc})
+ };
+ var template = s.dtHeaderEcho;
+ JSKitLib.fmap(replacements, function(replacement, pattern) {
+ template = template.replace(new RegExp("{" + pattern + "}", "g"), replacement);
+ });
+ header = JSKitLib.html(s.gtmpl(template));
+ JSKitLib.mapClass2Object(s.TC, header);
+ if (s.TC["jsk-HeaderInfoBoxImg"]) JSKitLib.addPNG(s.TC["jsk-HeaderInfoBoxImg"], "//cdn.js-kit.com/images/echo.png");
+ s.renderPauseIndicator();
+ s.renderPauseCounter();
+ } else {
+ header = s.div();
+ }
+ return header;
+}
+
+JSCC.prototype.assembleImagesUploadForm = function(uInp, imgArea) {
+ var s = this;
+ var tc = s.TC;
+ s.imgArea = imgArea;
+ var handler = function(e){
+ e = e || window.event;
+ if(e.keyCode == 27 || e.which == 27) JSKitLib.preventDefaultEvent(e);
+ };
+ if (uInp && !uInp.ifri){
+ var frmi = s.cr('form');
+ JSKitLib.setStyle(frmi, "clear: both;");
+ JSKitLib.addClass(frmi, "js-uploadImageForm");
+ frmi.method = 'post';
+ frmi.acceptCharset = 'UTF-8';
+ frmi.encoding = 'multipart/form-data';
+ frmi.style.margin = "0px";
+ var lbli = s.cr('div');
+ JSKitLib.addClass(lbli, "js-uploadImageInputLabel");
+ s.lbliChange = function(mode) {
+ JSKitLib.removeChildren(lbli);
+ lbli.appendChild(JSKitLib.html("" + $JCL(mode ? "loading" : "uploadImage") + " "));
+ }
+ s.lbliChange(0);
+
+ params = JSKitEPB.getAsHash({ref: JSKitLib.getRef(s)});
+ JSKitLib.fmap(params, function(v, k) {
+ var item = s.cr('input');
+ item.type = 'hidden';
+ item.name = k;
+ item.value = encodeURIComponent(v);
+ frmi.appendChild(item);
+ });
+
+ var upfi = s.cr('input');
+ s.imgUpload = upfi;
+ upfi.disabled = ( s.imgArea && s.imgArea.disableUpload ) ? true : false ;
+ upfi.type = 'file';
+ upfi.name = 'image';
+ var formitems = JSKitLib.mapClass2Object({}, frmi);
+ var val;
+ var fi = function() {
+ if(val) {
+ var subi = s.TC["js-Cmtsubmit"];
+ subi.disabled = false;
+ upfi.disabled = false;
+ frmi.reset();
+ JSKitLib.fmap(params, function(v, k) {
+ formitems[k].value = encodeURIComponent(v);
+ });
+ JSKitLib.removeEventHandler(document, ["keydown"], handler);
+ s.getImages(val);
+ val = undefined;
+ }
+ }
+ var tgti = 'js-ifrm-'+s.jcaIndex + Math.random();
+ var ifri = JSKitLib.createHiddenIframe(tgti, uInp, fi, false);
+ frmi.target = tgti;
+ upfi.onchange = function() {
+ val = (new Date()).getUTCMilliseconds() + "-" + Math.random( );
+ frmi.action = s.uriImage+'add?rnd='+val;
+ s.lbliChange(1);
+ frmi.submit();
+ var subi = s.TC["js-Cmtsubmit"];
+ subi.disabled = true;
+ upfi.disabled = true;
+ JSKitLib.addEventHandler(document, ["keydown"], handler);
+ };
+ uInp.appendChild(lbli)
+ frmi.appendChild(upfi);
+ uInp.appendChild(frmi);
+ uInp.ifri = ifri;
+ }
+ s.preventAnonymousComments();
+}
+
+JSCC.prototype.assembleEchoBrand = function() {
+ var template =
+ '';
+ return JSKitLib.toDOM(template, "js-poweredBy-", {}).content;
+}
+
+JSCC.prototype.isSourceAvailable = function(source) {
+ var filter = this.sourceFilter;
+ if (!filter || !this.useEcho()) return true;
+ source = filter.normalize(source);
+ var sourceInList = filter.sources.hash.hasOwnProperty(source);
+ return sourceInList ? filter.sources.hash[source] : filter.type == "exclude";
+}
+
+JSCC.prototype.avatarsManagerWrapper = function(element) {
+ this.avatarsManager.assembleAvatarArea(element);
+}
+
+JSCC.prototype.dataLoader = function(so, nc) {
+ var s = this;
+ var so = s.serverOptions;
+ var tc = s.TC;
+ var d = function(){return s.div.apply(s,arguments);}
+
+ if (this.config.disabled != 'no') return;
+
+ var cc = JSKitLib.html(s.gtmpl(s.utmpl['js-CreateComment'] || (s.config.nolc ? s.dtProfileCreate : s.dtCreate)));
+ JSKitLib.mapClass2Object(tc, cc);
+ JSKitLib.attachDescriptors2Elements(tc, "js-kit-lcf-", this);
+ if (JSKitEPB.isExists()) {
+ JSKitLib.fmap(['Name', 'Email'], function(field) {
+ if (tc['js-Cmt' + field]) {
+ tc['js-Cmt' + field].disabled = true;
+ }
+ });
+ }
+ var ec = JSKitLib.html(s.gtmpl(s.dtEditComment));
+ JSKitLib.mapClass2Object(tc, ec);
+ if(s.config.profileLC) {
+ var cin = tc['js-commentInputName'];
+ if(cin) cin.style.display = 'none';
+ var cie = tc['js-commentInputEmail'];
+ if(cie) cie.style.display = 'none';
+ }
+ if(so.extraFieldURL) {
+ var ciu = tc['js-commentInputUrl'];
+ if (ciu) ciu.style.display = 'block';
+ }
+ var ac = function(name, cb) {
+ var o = tc['js-'+name];
+ if(!o) return;
+ if(o.tagName == 'A') o.href="javascript:void(0);";
+ o.style.cursor = 'pointer';
+ o.onselectstart = function() { return false; }
+ o.onclick = cb;
+ }
+
+ var uInp = tc['js-uploadImageInput'];
+ var uInpW = tc['js-uploadImageInputWrapper1'];
+
+ s.clearImgs = function(){
+ JSKitLib.removeChildren(s.imgArea);
+ if(uInpW) uInpW.style.paddingTop = '0px';
+ if(uInp && uInp.ifri) {
+ JSKitLib.removeChildren(uInp);
+ JSKitLib.hide(uInp);
+ uInp.ifri = undefined;
+ }
+ if(s.images) delete(s.images);
+ }
+
+ JSKitLib.fmap(['', 'Edit'], function(el, i) {
+ ac('Cmtsubmit' + el, function() {
+ s.pause.forced = false;
+ s.CommentSubmitted();
+ return false;
+ });
+ ac('Cmtcancel' + el, function() {
+ s.clearImgs();
+ if(s.onCancel) s.onCancel();
+ s.CommentCancelled();
+ if (s.useReplyThreadsCollapsing() && s.replyForId) {
+ var pageNo = s.curPage;
+ var comment = s.objById[s.replyForId];
+ delete s.replyForId;
+ if (comment) s.markCollapsedReplies(comment);
+ s.pause.forced = false;
+ s.curPage = 0;
+ s.displayPage(pageNo);
+ }
+ return false;
+ });
+ });
+ if (JSKitLib.isIE()) {
+ var op = tc['js-commentOptions'];
+ var sub = tc['js-commentSubmit'];
+ if (op) op.style.paddingLeft = "3px";
+ if (sub) sub.style.paddingLeft = "3px";
+ }
+
+ s.anonymousCmt = so.anonymousCmt;
+
+ if (tc["js-commentAvatar"]) s.avatarsManager.assembleAvatarArea(tc["js-commentAvatar"]);
+
+ if (s.getSkin() != 'echo') {
+ s.setFormFields({'Email': '', 'Url': ''});
+ s.wrapJSKAuth();
+ }
+ s.preventAnonymousComments();
+
+ ac('commentOpenIDLogout', function() {
+ setTimeout(function(){
+ var gfc = s.jskauth.getAuthIdentity("gfc");
+ if(gfc && gfc.params.site && gfc.user) {
+ new JSKitGFC(
+ JSKitLib.getRef(s),
+ s.target,
+ gfc.params.site,
+ function(){
+ this.processLogout();
+ });
+ }
+ s.server(s.uriDomain + '/api/session/logout.js', {});
+ }, 0);
+ return false;
+ });
+ if(!tc['js-commentMore']) {
+ var m = tc['js-CCMore'];
+ if(m) m.style.display = 'none';
+ }
+
+ s.onAddImgButton = function(isShow) {
+ if(s.commentPostingProcess) {
+ alert($JCL('messagePostingInProgress'));
+ return;
+ }
+ if(s.config.uploadImages) {
+ s.imgArea = tc['js-commentImageArea'];
+ if(uInp && s.imgArea) {
+ uInp.style.display = isShow ? 'block' : 'none';
+ if(uInpW) uInpW.style.paddingTop = isShow ? '15px' : '0px';
+ s.imgShow = isShow;
+ }
+ }
+ s.assembleImagesUploadForm(uInp, s.imgArea);
+ };
+
+ var uImg = tc['js-uploadImageButton'];
+ if (uInp) JSKitLib.hide(uInp);
+ if(uInp && uImg && !s.config.uploadImages) {
+ JSKitLib.hide(uImg);
+ JSKitLib.hide(uInp);
+ }
+ ac('uploadImageButton', function(){
+ s.onAddImgButton(!JSKitLib.visible(uInp));
+ });
+
+ var toggleAvatarArea = function(isVisible) {
+ JSKitLib.fmap(["Avatar", "AvatarLabel"], function(key) {
+ var element = tc["js-comment" + key];
+ if (!element) return;
+ JSKitLib[isVisible ? "show" : "hide"](element);
+ });
+ };
+ if (s.getSkin() == "") {
+ toggleAvatarArea(false);
+ }
+ var onCommentMore = function(obj, label) {
+ obj.ashown = !obj.ashown;
+ JSKitLib.text(obj.ashown ? label.less : label.more, obj, true);
+ s.onAddImgButton(obj.ashown);
+ toggleAvatarArea(obj.ashown);
+ return false;
+ };
+
+ ac('commentAddAvatar', function() {
+ var label = {'less': '-', 'more': '+'};
+ return onCommentMore(this, label);
+ });
+ ac('commentMore', function() {
+ var label = {'less': this.getAttribute("less") || $JCL('less'),
+ 'more': this.getAttribute("more") || $JCL('more') };
+ return onCommentMore(this, label);
+ });
+
+ if (!tc["js-commentAvatar"] && (!s.config.uploadImages || tc['js-uploadImageButton'] || !tc['js-uploadImageInput'])) {
+ JSKitLib.fmap(['js-commentMore', 'js-CCMore'], function(element) { if (tc[element]) JSKitLib.hide(tc[element]); });
+ }
+
+ if(so.mmode == "pause" || !s.isSourceAvailable("Comments")) {
+ var lca = null;
+ } else {
+ var lca = d('js-commentControl', s.a(s.JCL('leaveComment')));
+ lca.onclick = function() { return s.ShowCommentDialog(); };
+ }
+
+ var jmg = d('js-commentControl js-commentTool', JSKitLib.html('@ '), s.a($JCL("controls")));
+ jmg.onclick = function() {
+ var srt = ["date", "name"];
+ if(!s.config.moderate && s.scoringEnabled()) srt.push("karma");
+ if(s.adminMode) srt.push("status");
+ /* s.submitRating check is not good for all the cases */
+ if ( $JSKitGlobal.isRatingsAppAvailable() ) srt.push("rating");
+ var srtOpts = [];
+ for(var i = 0; i < srt.length; i++) {
+ srtOpts.push(''
+ +$JCL(srt[i])+' ');
+ }
+ var bkw = ["ascending", "descending"];
+ var bkwOpts = [];
+ for(var i = 0; i < bkw.length; i++) {
+ bkwOpts.push(''
+ +$JCL(bkw[i])+' ');
+ }
+ var prs = ["on (threaded)", "off (flat)"];
+ var prsMap = {'on (threaded)':'yes','off (flat)':'no'}
+ var prsOpts = [];
+ for(var i = 0; i < prs.length; i++) {
+ prsOpts.push(''
+ +$JCL(prs[i])+' ');
+ }
+ var div = s.cr("div");
+ div.innerHTML =
+ ""
+ + "" + $JCL("sortBy") + ' '
+ + srtOpts.join("")
+ + " "
+ + "" + $JCL("order") + ' '
+ + bkwOpts.join("")
+ + " "
+ + "" + $JCL("threading") + ' '
+ + prsOpts.join("")
+ + " "
+ + "" + $JCL("search") + ' '
+ + (s.adminMode && !s.config.moderate?('Moderate whole site '):'')
+ + "
"
+ this.notShowIfr = true;
+ s.settingsWindow('ctWnd', this, div);
+ var obj={'mode': 'form', 'inpSize': '121px', type: 'Search'};
+ var form = new JSIPE(obj);
+ obj.jsk$on_submit_exit = function(){
+ s.searchString = form.input.value;
+ s.viewControl({name: "search"});
+ s.hideSettingsWindow('ctWnd');
+ }
+ form.input.value = s.searchString || "";
+ if (s.searchString) form.cleaner.style.visibility = "visible";
+ var sCell = document.getElementById("js-SearchCell-"+s.jcaIndex);
+ if (sCell) s.addChild(sCell, form.main);
+
+ return false;
+ }
+ s.controls = jmg;
+ if(nc || s.config.moderate) {
+ s.controls.reveal = function(){};
+ } else {
+ s.controls.style.display = 'none';
+ s.controls.reveal = function(){s.controls.style.display=''}
+ }
+
+ var pb;
+ if(so.subs || so.noJunk || so.whitelabel) {
+ pb = "";
+ } else {
+ if (s.getSkin() != "echo") {
+ var propLink = JSKitLib.html('Powered by JS-Kit ');
+ var prop = d('', "(", propLink, ")");
+ prop.style.position = 'relative';
+ pb = d("js-commentControl js-poweredBy", prop);
+ }
+ }
+
+ var ca = d("js-CommentsArea",
+ (s.config.nolc && !s.IM)?null:d("js-LeaveComment", s.config.moderate || s.IM=='own' ?null:lca, s.IM ? null : jmg, !s.config.nolc ? pb : null,
+ JSKitLib.html(' ')),
+ tc["js-CreateComment"], tc["js-EditComment"]);
+ this.makeWelcomePanel();
+
+ if (!so.wysiwyg && so.smiley) {
+ JSKitLib.fmap(['Text', 'TextEdit'], function(v) {
+ var sd = s.cr('div');
+ sd.style.margin = '3px 0px 0px 3px';
+ var text = tc['js-Cmt' + v];
+ var processed = {};
+ var index = 0;
+ JSKitLib.fmap(s.smiles, function(el, i) {
+ if (!processed[el.file]) {
+ processed[el.file] = 1;
+ var smile = JSKitLib.html(s.smileTag(el));
+ smile.style.display = 'inline';
+ smile.style.cursor = 'pointer';
+ smile.style.marginRight = '5px';
+ smile.onclick = function() {
+ if (s.getSkin() == "echo" && JHI2.isEmpty(text)) {
+ JHI2.set(text, i);
+ } else text.value += ' ' + i;
+ text.focus();
+ if (JSKitLib.isSafari()) {
+ text.setSelectionRange(text.value.length, text.value.length);
+ }
+ };
+ sd.appendChild(smile);
+ }
+ });
+ var element = (s.getSkin() == "echo") ? s.TC[v == "Text" ? "jsk-CommentFormBody" : "jsk-CommentEditFormBody"] : text;
+ element.parentNode.insertBefore(sd, element.nextSibling);
+ });
+ }
+
+ var pageNavTop = s.config.skin == 'echo' ? null : d('js-PageNavTop');
+ var pageNavBottom = d('js-PageNavBottom');
+ var header = s.getThreadHeader();
+ var thread = d("jsk-ThreadWrapper jsk-PrimaryFont jsk-PrimaryBackgroundColor", pageNavTop, d("js-OldCommentsWrap jsk-StreamWrapper", d("js-OldComments")), pageNavBottom);
+ s.TC["jsk-ThreadWrapper"] = thread;
+ if(s.config.backwards == 'yes') {
+ s.addChild(ca, header);
+ s.addChild(ca, thread);
+ } else {
+ s.addChild(ca, thread, true);
+ s.addChild(ca, header, true);
+ }
+ if (s.getSkin() == "echo" && !so.whitelabel) s.addChild(thread, s.assembleEchoBrand());
+ if(s.useEcho()) {
+ JSKitLib.setMouseEvent(thread, "over", function() { s.setStreamState(true); });
+ JSKitLib.setMouseEvent(thread, "out", function() { s.setStreamState(false); });
+ }
+ var pageToDisplay = so.pages.sp;
+ var dpCB;
+ if(s.comment_location) {
+ var obj = s.jspg.getItemById(s.comment_location);
+ if(obj) {
+ pageToDisplay = s.jspg.getPageByItemId(s.comment_location) + 1;
+ dpCB = function() {
+ if(obj.div) s.flash(obj.div);
+ };
+ }
+ delete s.comment_location;
+ }
+ s.displayPage(pageToDisplay, dpCB);
+
+ var closeControlsPopup = function() {
+ s.hideSettingsWindow('ctWnd');
+ s.hideSettingsWindow('ctBlock');
+ }
+ JSKW$Events.registerEventCallback(undefined, closeControlsPopup, "comments_closeControlsPopup");
+
+ ca.onclick = function() {
+ closeControlsPopup();
+ JSKW$Events.syncBroadcast("miniProfile_collapseAll");
+ }
+ s.addChild(s.target, ca);
+ if (lca && !s.config.moderate && (s.config.nolc && s.IM == 'foreign' || (so.expandLeaveCmt && !s.config.noautoexpand)) && !s.config.userProfileComments) {
+ s.ShowCommentDialog(undefined, {nofocus: true});
+ }
+}
+
+JSCC.prototype.objRerender = function(obj, cmt) {
+ cmt.ctls['js-singleCommentText'].innerHTML =
+ this.tmpl("{Text}", obj, true);
+}
+
+JSCC.prototype.getLastReply = function(pobjId) {
+ var pobj = this.jspg.getItemById(pobjId);
+ var lreplyObj = null;
+ for(var i=pobj.obj.thread.length-1; i>=0; i--){
+ if(pobj.obj.thread[i].status!='D') {
+ var c = this.jspg.getItemById(pobj.obj.thread[i].ID);
+ if(c) {
+ lreplyObj = this.getLastReply(c.obj.ID);
+ break;
+ }
+ }
+ }
+ return lreplyObj || pobj;
+}
+
+JSCC.prototype.reCalcPages = function() {
+ if(this.curPage>this.jspg.pageCount) this.displayPage(this.jspg.pageCount);
+ this.rePageNavigator(this.jspg.pageCount>0 ? this.jspg.pageCount-1 : undefined);
+}
+
+JSCC.prototype.appendConversation = function (cmt, conversation) {
+ var cnvsObj = {};
+ var cnvs = this.conversations[conversation];
+ if(!cnvs) return;
+ JSKitLib.fmap(["Name","avatar","avatarHeight","avatarWidth"],
+ function(V){ cnvsObj[V] = cnvs.direction=="in" ? cnvs[V] : cnvs["dest"+V] });
+ cnvsObj.Label = "Conversation with ";
+ var dtc = JSKitLib.html(this.tmpl(this.dtConversation, cnvsObj));
+ var ctls = JSKitLib.mapClass2Object({}, dtc);
+ var nm = ctls['js-ConversationName'];
+ if(nm && this.serverOptions.showProfile) {
+ nm.style.textDecoration = 'underline';
+ this.appendProfileHandler(nm, {profile: cnvs.profile});
+ }
+ cmt.insertBefore(dtc, cmt.firstChild);
+ JSKitLib.addClass(cmt, "js-singleCommentConversationHead");
+}
+
+JSCC.prototype.removeConversation = function (cmt) {
+ JSKitLib.removeClass(cmt, "js-singleCommentConversationHead");
+ cmt.removeChild(cmt.firstChild);
+}
+
+JSCC.prototype.appendConversationChild = function (cmt) {
+ JSKitLib.addClass(cmt, "js-singleCommentConversationChild");
+}
+
+JSCC.prototype.removeConversationChild = function (cmt) {
+ JSKitLib.removeClass(cmt, "js-singleCommentConversationChild");
+}
+
+JSCC.prototype.getSkin = function() {
+ return this.config.skin==="wireframe" ? "" : (this.config.skin || "");
+}
+
+JSCC.prototype.generateEventParams = function(extra_params) {
+ extra_params = extra_params || {};
+ var s = this;
+ var params = {
+ jcaIndex: s.jcaIndex,
+ uniq: s.config.path.replace(/^\//, ''),
+ domain: s.config.domain
+ };
+ JSKitLib.fmap(extra_params, function(v, k) {
+ params[k] = v;
+ });
+ return params;
+}
+
+JSCC.prototype.publishEvent = function(event_name, params) {
+ JSKitAPI.publish(event_name,
+ this.generateEventParams(params));
+}
+
+JSCC.prototype.eventsHandler = function(eventName, eventParams) {
+ var self = this;
+ var so = self.serverOptions;
+ eventParams = eventParams || {};
+ switch (eventName) {
+ case "comment-deleting":
+ var item = self.jspg.getItemById(eventParams.cmtId);
+ if(!item || !item.div) return;
+ var div = item.div;
+ if(div.domCtls) div.domCtls.style.visibility = "hidden";
+ var av = div.ctls['js-singleCommentAvatar'];
+ self.placeProcessAvatar(av);
+ item.obj.origstatus = item.obj.status;
+ item.obj.status = 'DP';
+ item.obj.dTimer = setTimeout(function(){
+ item.obj.status = 'A';
+ if(div.domCtls) div.domCtls.style.visibility = "";
+ if(av) self.placeAvatar(item.obj, av);
+ delete item.obj.dTimer;
+ }, 30000);
+ break;
+
+ case "comment-deleted":
+ var item = self.jspg.getItemById(eventParams.cmtId);
+ if(!item || !item.div) return;
+ var div = item.div;
+ if(item.obj.dTimer) clearTimeout(item.obj.dTimer);
+ if(item.obj.ParentID) {
+ var parentCmt = self.objById[item.obj.ParentID];
+ if (parentCmt) {
+ parentCmt.thread = JSKitLib.filter(function(obj) {
+ return obj.ID != eventParams.cmtId;
+ }, parentCmt.thread);
+ }
+ self.markCollapsedReplies(self.objById[eventParams.cmtId]);
+ } else {
+ if (self.useReplyThreadsCollapsing()) {
+ self.removeRepliesExpandMarker(item.obj);
+ }
+ }
+ so.pages.tc -= self.removeComment(div, true);
+ self.publishEvent("comments-count-updated", {'count': so.pages.tc});
+ break;
+
+ case "comment-added":
+ so.pages.tc++;
+ self.publishEvent("comments-count-updated", {'count': so.pages.tc});
+ break;
+
+ case "comments-data-loaded":
+ self.publishEvent("comments-count-updated", {'count': so.pages.tc});
+ break;
+
+ case "comments-count-updated":
+ self.refreshThreadHeader();
+ if(self.popupInstance) {
+ var title = self.replaceCountTemplate(self.config['popup-title'],
+ eventParams.count);
+ self.popupInstance.updateTitle(title);
+ }
+ if(self.parentWidget && self.parentWidget.popupLink) {
+ self.drawCommentLink.call(self.parentWidget, eventParams.count);
+ }
+ break;
+ case "user-login":
+ if (self.config['display-mode'] == "inline") {
+ var nofocus = typeof(eventParams.nofocus) == "undefined"
+ || eventParams.nofocus;
+ self.refreshComments({"nofocus": nofocus});
+ }
+ break;
+ case "user-logout":
+ if (self.config['display-mode'] == "inline") {
+ var nofocus = typeof(eventParams.nofocus) == "undefined"
+ || eventParams.nofocus;
+ JSKW$Events.invalidateContext(self.miniProfileCtx);
+ setTimeout(function(){
+ self.refreshComments({"nofocus": nofocus});
+ }, 0);
+ }
+ break;
+ }
+}
+
+JSCC.prototype.refreshThreadHeader = function() {
+ var hdr = this.TC['jsk-HeaderWrapper'];
+ if(hdr && hdr.parentNode) {
+ hdr.parentNode.replaceChild(this.getThreadHeader(), hdr);
+ this.addAdminMenu(this.TC['jsk-MenuAdmin']);
+ }
+}
+
+JSCC.prototype.makeWelcomePanel = function() {
+ var s = this;
+ if (s.jcaIndex) return;
+ if (!s.adminMode) {
+ s.deleteWelcomePanel();
+ return;
+ }
+ if (s.TC['js-WelcomePanel'] || s.config.moderate || s.config.nolc) return;
+
+ var wp_html = ''
+ + ''
+ + '
'
+ + '
'
+ + ''
+ + ((s.serverOptions.welcome || {}).message || $JCL('welcomeToComments'))
+ + '
'
+ + '
'
+ + '
{Label:getStarted}: '
+ + '
'
+ + ' '
+ + ' '
+ + ' '
+ + ' '
+ + '
'
+ + '
'
+ + '
'
+ + '
{Label:getInvolved}: '
+ + '
'
+ + ' '
+ + ' '
+ + ' '
+ + '
'
+ + '
'
+ + '
'
+ + '
'
+ + '
'
+ + '
'
+ + '
';
+ var wp = JSKitLib.html(s.gtmpl(wp_html));
+ JSKitLib.mapClass2Object(s.TC, wp);
+ s.TC['js-WelcomePanelClose'].onclick = function() {
+ s.TC['js-WelcomePanel'].style.display = 'none';
+ if (s.serverOptions.welcome && s.serverOptions.welcome.ts) {
+ s.server('s-welcome-close', {'ts':
+ s.serverOptions.welcome.ts});
+ }
+ }
+ s.appendProfileHandler(s.TC['js-WelcomeProfileLink'], {profile: s.serverOptions.profile});
+ JSKitLib.addPNG(s.TC['js-WelcomePanelArrow'], s.uriDomain + "/images/welcome/triangle.png");
+ var lc = s.TC['js-LeaveComment'];
+ if (lc) lc.parentNode.insertBefore(wp, lc);
+}
+
+JSCC.prototype.deleteWelcomePanel = function() {
+ if (this.TC['js-WelcomePanel']) {
+ this.TC['js-WelcomePanel'].parentNode.removeChild(this.TC['js-WelcomePanel']);
+ delete this.TC['js-WelcomePanel'];
+ }
+}
+
+JSCC.prototype.addMenu = function(cmt, obj) {
+ var self = this;
+ var showOffensive = this.serverOptions.commod && !obj.yours && !this.config.nolc && (!obj.msgtype || !obj.msgtype.match(/T|P/) || this.serverOptions.trackbackreply);
+ var showProfile = obj.profile && self.serverOptions.showProfile && !(obj.msgtype && obj.msgtype.match(/T|P/)) && !this.config.nolc;
+ var cmtURL = ((obj.permalink || this.config.permalink).replace(/#jsid-*/, "") + "#") + obj.ID;
+ var data = [
+ {title: $JCL("showUserProfile"), action: function() {self.showProfile(cmt.firstChild, obj);}, hidden: !showProfile, icon: this.uriDomain + "/images/menu/show-user-profile.png"},
+ {title: $JCL("markAsOffensive"), icon: this.uriDomain + "/images/menu/mark-comment-as-offensive.png", action: function(){self.markOffensive(obj.ID)}, hidden: !showOffensive},
+ {title: $JCL("getPermalinkURL"), icon: this.uriDomain + "/images/menu/comment-permalink.png", inputValue: cmtURL, type: "DTI"}
+ ];
+ if (!this.serverOptions.whitelabel) {
+ data.push({type: "Delimeter"});
+ data.push({title: $JCL("getWidgetLikeThis"), action: function() { window.open("http://js-kit.com/comments?menu", "_blank");}, statusText: "http://js-kit.com/comments?menu"});
+ }
+ var mtgt = this.config.nolc ? self.target.parentNode.parentNode : undefined;
+ return JSMenu($JCL("options"), data);
+}
+
+JSCC.prototype.addAdminMenu = function(container) {
+ if (!container) return;
+ var s = this;
+ var so = s.serverOptions;
+ var isEPB = JSKitEPB.isExists();
+ var isLogged = s.jskauth.isLogged();
+ var isCmtAvailable = s.isSourceAvailable("Comments");
+ var showProfile = function() {
+ s.showProfile(container, {"profile": so.profile}, {"activeSection": "editProfile"});
+ };
+ var mkItem = function(label, icon, action, guard, extra) {
+ return guard ? JSKitLib.foldl({
+ "icon": icon ? '//cdn.js-kit.com/images/menu/' + icon : undefined,
+ "title": $JCL("menu" + label),
+ "action": action
+ }, extra || {}, function(value, acc, key) { acc[key] = value; }) : [];
+ };
+ var mkLink = function(label, icon, url, guard, disabled) {
+ return mkItem(label, icon, function() { window.open(url, '_blank'); }, guard, {
+ "disabled": disabled,
+ "statusText": url
+ });
+ };
+ var mkDelimeter = function(guard) {
+ return guard ? {"type": "Delimeter"} : [];
+ };
+ var items = JSKitLib.merge(
+ mkItem("Logout", "key.png", function() { s.jskauth.logout(); },
+ !isEPB && isLogged && isCmtAvailable),
+ mkItem("Login", "key.png", function() { s.jskauth.show(); },
+ !isEPB && !isLogged && isCmtAvailable),
+ mkItem("EditProfile", "user-edit.png", function() { showProfile(); },
+ so.showProfile && isCmtAvailable && !so.isNullSession),
+ mkItem("Follow", "follow.png", function() { s.openFollowPopup(); },
+ !isEPB && isCmtAvailable, {"disabled" : so.anonymousCmt && !isLogged}),
+ mkDelimeter(isCmtAvailable),
+ mkLink("Moderation", "comment-edit.png", s.uriDomain + "/moderate/",
+ isCmtAvailable, !so.adminMode),
+ mkLink("Settings", "wrench.png", s.uriDomain + "/settings/",
+ isCmtAvailable, !so.adminMode),
+ mkLink("AdminNotices", null, "http://blog.js-kit.com/tag/admin/",
+ isCmtAvailable, !so.adminMode),
+ mkDelimeter(isCmtAvailable && !so.whitelabel),
+ mkLink("GetThis", "script-code.png", s.uriDomain + "/comments?menu",
+ !so.whitelabel),
+ mkLink("JSKBlog", "newspaper.png", "http://blog.js-kit.com/",
+ !so.whitelabel),
+ mkLink("JSKTwitter", "twitter-favicon.png", "http://twitter.com/echoenabled",
+ !so.whitelabel),
+ mkLink("Help", "information.png", s.uriDomain + '/support/',
+ !so.whitelabel)
+ );
+ if (!items.length) {
+ JSKitLib.removeChildren(container);
+ return;
+ }
+ JSKitLib.replaceChildren(container, JSMenu($JCL("menuAdmin"), items, "", s.target));
+}
+
+JSCC.prototype.getSelectedIdentities = function() {
+ var self = this;
+ var format = function(type, prefix, filter) {
+ return JSKitLib.fmap(self.jskauth.getIdentities(type), function(identity) {
+ if (!filter || filter(identity)) {
+ var flag = identity.use_as_from ? "checked" : "unchecked";
+ return [prefix + identity.type, identity.url || '', flag, false];
+ }
+ });
+ }
+ var identities = JSKitLib.merge(
+ format("auth", "login-", function(identity) { return !!identity.user; }),
+ format("web", ""));
+ return JSKitLib.Object2JSON(identities);
+}
+
+JSCC.prototype.constructFromToButtons = function(type) {
+ var template =
+ '';
+ var descriptors = {
+ "BarExpandMarker" : function(element){ JSKitLib.addPNG(element, "//cdn.js-kit.com/images/common/arrow-down-10x10.png") }
+ };
+ return JSKitLib.toDOM(template, "jskit-GoogleLikeMenu", descriptors).content;
+}
+
+JSCC.prototype.fromMenuAnonymous = function() {
+ var self = this;
+ var template =
+ '';
+ var updateAnonymousURL = function(url) {
+ if (typeof url == "object") url = url[1];
+ self.extraFormFields["Url"] = url;
+ };
+ var identities = JSKitLib.fmap(self.jskauth.getIdentities("auth"), function(identity) {
+ return {
+ "icon": JSKAuth.prototype.getIdentityParam('favicon', identity, "//cdn.js-kit.com/images/favicons/" + identity.type + ".png"),
+ "type": "Checkbox",
+ "state": "disabled",
+ "title": JSKAuth.prototype.getIdentityParam('long_label', identity, JSKAuth.prototype.getIdentityLabel(identity.type, true)),
+ "action": function() { self.jskauth.show(identity.type); }
+ };
+ });
+ var items = JSKitLib.merge(
+ {"type": "HTML", "title": JSKitLib.html('')},
+ identities,
+ self.serverOptions.extraFieldURL ? [
+ {
+ "type": "HTML",
+ "title": JSKitLib.html(''),
+ "hidden": self.serverOptions.anonymousCmt
+ },
+ {
+ "type": "SRCheckbox",
+ "icon": "//cdn.js-kit.com/images/favicons/default.png",
+ "title": self.extraFormFields["Url"] || $JCL("myURL"),
+ "oncreate": updateAnonymousURL,
+ "onupdate": updateAnonymousURL,
+ "deletable": false,
+ "unclonable": true,
+ "hideCheckbox": true,
+ "hidden": self.serverOptions.anonymousCmt
+ }
+ ] : [],
+ {"type": "HTML", "title": JSKitLib.html('')}
+ );
+ var menu = JSMenu(self.constructFromToButtons("from"), items, "HTML");
+ var descriptors = {
+ "control": function() {
+ return menu;
+ },
+ "field": function(element) {
+ self.renderNameField(element, "js-kit-from-name");
+ if (self.serverOptions.anonymousCmt) {
+ JSKitLib.preventSelect(element);
+ JSKitLib.addEventHandler(element, ['click'], function(e) {
+ JSKitLib.stopEventPropagation(e);
+ JSKW$Events.syncBroadcast('JSMenu-Opened', menu);
+ });
+ }
+ }
+ };
+ return JSKitLib.toDOM(template, "js-kit-from-", descriptors).content;
+}
+
+JSCC.prototype.setNameFieldValue = function() {
+ var input = this.TC["js-CmtName"];
+ if (!input) return;
+ JHI2.remove(input);
+ input.value = (!JHI2.isEmpty(input) && input.value) || this.extraFormFields["Name"] || "";
+ JHI2.create(this.serverOptions.requireUsername ? $JCL("yourNameRequired") : $JCL("yourNameHere"), input);
+}
+
+JSCC.prototype.renderNameField = function(container, className, readonly) {
+ var element;
+ var anonymousCondition = this.serverOptions.anonymousCmt && !this.jskauth.isLogged();
+ if (readonly || anonymousCondition) {
+ var text = this.extraFormFields["Name"] || "";
+ if (anonymousCondition) {
+ text = $JCL("loginRequiredNotice");
+ JSKitLib.addClass(container, "js-kit-disabledNameField");
+ }
+ element = JSKitLib.html("" + text + "
");
+ } else {
+ element = JSKitLib.html(" ");
+ if(this.TC) this.TC["js-CmtName"] = element;
+ JSKitLib.addEventHandler(container, ["click"], function(e) {
+ JSKitLib.stopEventPropagation(e);
+ element.focus();
+ });
+ element.title = $JCL("clickToEdit");
+ this.setNameFieldValue();
+ }
+ JSKitLib.replaceChildren(container, element);
+}
+
+JSCC.prototype.fromMenuActionsHandler = function(identity, action, data) {
+ var self = this;
+ var rerenderUserInfo = function() {
+ self.userInfoWrapper(self.TC["js-kit-lcf-userInfoWrapper"]);
+ }
+ var rerenderLinksIcon = function() {
+ self.miniProfile.render("siteLinksIcons", {"identities": self.jskauth.getIdentities()});
+ }
+ switch (action) {
+ case "delete": if (identity.group == "web") {
+ self.jskauth.identityServerAction("unbind", identity, {}, rerenderLinksIcon);
+ break;
+ };
+ case "delete":
+ var loggedCount = JSKitLib.foldl(0, self.jskauth.getIdentities("auth"), function(identity, acc) {
+ return acc += identity.user ? 1 : 0;
+ });
+ var firstConfirmed;
+ if (
+ (firstConfirmed = confirm($JCL("confirmMessage_unbindAccount"))) && loggedCount > 1
+ || firstConfirmed && loggedCount == 1 && confirm($JCL("confirmMessage_unbindLastAccount"))
+ ) {
+ self.jskauth.identityServerAction("unbind", identity, {}, rerenderUserInfo);
+ }
+ break;
+ case "create":
+ self.jskauth.identityServerAction("bind", identity, {}, rerenderLinksIcon);
+ break;
+ case "update":
+ self.jskauth.identityServerAction("update", identity, {url: data[1]}, rerenderLinksIcon);
+ break;
+ case "check":
+ identity.use_as_from = true;
+ rerenderLinksIcon();
+ break;
+ case "uncheck":
+ identity.use_as_from = false;
+ rerenderLinksIcon();
+ break;
+ }
+}
+
+JSCC.prototype.fromMenuLoggedIn = function() {
+ var self = this;
+ var identities = {"auth": {}, "web": {}};
+ var applyCallbacks = function(item) {
+ JSKitLib.fmap(["check", "uncheck", "delete", "update", "create"], function(action) {
+ item["on" + action] = function(data) {
+ if (!this.identity)
+ this.identity = self.jskauth.assembleIdentity(data, "home", "web");
+ self.fromMenuActionsHandler(this.identity, action, data);
+ }
+ });
+ return item;
+ }
+ var validateURLs = function(url) {
+ if(!url) {
+ alert($JCL("urlIsEmpty"));
+ return false;
+ }
+ for(var i = 0; i < this.parent.items.length; i++) {
+ if(this.parent.items[i].title == url && this.parent.items[i] != this) {
+ alert($JCL("urlAlreadyExists"));
+ return false;
+ }
+ }
+ return true;
+ }
+ identities.auth = JSKitLib.fmap(this.jskauth.getIdentities("auth"), function(identity) {
+ var state;
+ if (!identity.user) {
+ state = "disabled";
+ } else if (identity.use_as_from) {
+ state = "checked";
+ } else {
+ state = "unchecked";
+ }
+ return applyCallbacks({
+ "type": "Checkbox",
+ "icon": JSKAuth.prototype.getIdentityParam('favicon', identity, "//cdn.js-kit.com/images/favicons/" + identity.type + ".png"),
+ "state": state,
+ "title": identity.url,
+ "action": state == "disabled" ? function() { self.jskauth.show(identity.type); } : null,
+ "identity": identity,
+ "displayTitle": (function(){
+ if(identity.user) {
+ var Name;
+ if(identity.group == "epb" && JSKitEPB.isExists())
+ Name = JSKitEPB.getValue("Name");
+ Name = Name || identity.name || identity.user;
+ return Name + " @ " + JSKAuth.prototype.getIdentityParam('short_label', identity, JSKAuth.prototype.getIdentityLabel(identity.type));
+ } else {
+ return JSKAuth.prototype.getIdentityParam('long_label', identity, JSKAuth.prototype.getIdentityLabel(identity.type, true));
+ }
+ }()),
+ "deletable": identity.user && identity.group != 'epb',
+ "deleteLabel": $JCL("menuUnbindIdentity")
+ });
+ });
+ identities.web = JSKitLib.fmap(this.jskauth.getIdentities("web"), function(identity) {
+ return applyCallbacks({
+ "type": "SRCheckbox",
+ "icon": "//cdn.js-kit.com/images/favicons/default.png",
+ "state": identity.use_as_from ? "checked" : "unchecked",
+ "title": identity.url,
+ "identity": identity,
+ "alreadyEdited": true
+ });
+ });
+ var items = JSKitLib.merge(
+ {"type": "HTML", "title": JSKitLib.html('')},
+ identities.auth,
+ self.serverOptions.extraFieldURL ? JSKitLib.merge(
+ {
+ "type": "HTML",
+ "title": JSKitLib.html('')
+ },
+ identities.web,
+ applyCallbacks({
+ "type": "SRCheckbox",
+ "icon": "//cdn.js-kit.com/images/favicons/default.png",
+ "title": $JCL("myURL"),
+ "hideCheckbox": true
+ })
+ ) : [],
+ {"type": "HTML", "title": JSKitLib.html('')}
+ );
+ return JSMenu($JCL("addAnotherSite"), items);
+}
+
+JSCC.prototype.toMenu = function() {
+ var self = this;
+ var share = function(identity, publish) {
+ identity.publish = publish;
+ self.extraFormFields["Share-" + identity.type] = publish ? "on" : "off";
+ }
+ var sharingServices = JSKitLib.fmap(this.jskauth.getIdentities("auth"), function(identity) {
+ if (!identity.can_publish) return;
+ self.extraFormFields["Share-" + identity.type] = "off";
+ var sharing_available = identity.user && !identity.expired;
+ return {
+ "type": "Checkbox",
+ "icon": "//cdn.js-kit.com/images/favicons/" + identity.type + ".png",
+ "title": $JCL("shareWith_" + identity.type),
+ "state": sharing_available ? (identity.publish || self.$temp_publish == identity.type ? "checked" : "unchecked") : "disabled",
+ "action": sharing_available ? null : function() {
+ self.$temp_publish = identity.type;
+ self.jskauth.show(identity.type);
+ },
+ "oninit": function() {
+ if (sharing_available && (identity.publish || self.$temp_publish == identity.type)) this.oncheck(this.title);
+ },
+ "oncheck": function(title) {
+ var item = this;
+ share(identity, true);
+ item.dt = cnt.insertBefore(
+ JSDogtag({
+ "text": title,
+ "icon": "//cdn.js-kit.com/images/favicons/" + identity.type + ".png",
+ "onclose": function() {
+ item.setState("unchecked");
+ cnt.removeChild(item.dt);
+ share(identity, false);
+ }
+ }),
+ cnt.lastChild);
+ },
+ "onuncheck": function(title) {
+ share(identity, false);
+ if (this.dt) cnt.removeChild(this.dt);
+ }
+ };
+ });
+ var items = JSKitLib.merge(
+ {"type": "HTML", "title": JSKitLib.html('')},
+ {
+ "type": "Checkbox",
+ "icon": "//cdn.js-kit.com/images/favicons/default.png",
+ "title": $JCL("thisPage"),
+ "state": "checked-disabled"
+ },
+ sharingServices,
+ {"type": "HTML", "title": JSKitLib.html('')});
+
+ var cnt = JSKitLib.cr({className: "js-kit-lcf-toField"});
+ cnt.appendChild(new JSDogtag({"text": $JCL("thisPage"), "icon": "//cdn.js-kit.com/images/favicons/default.png"}, cnt));
+ cnt.appendChild(JSKitLib.html('
'));
+ var menu = JSMenu(self.constructFromToButtons("to"), items, "HTML");
+ cnt.insertBefore(menu, cnt.firstChild);
+ JSKitLib.addEventHandler(cnt, ['click'], function(e) {
+ JSKitLib.stopEventPropagation(e);
+ JSKW$Events.syncBroadcast('JSMenu-Opened', menu);
+ });
+ delete this.$temp_publish;
+ return cnt;
+}
+
+JSCC.prototype.miniProfileWrapper = function(target) {
+ var self = this;
+ var so = this.serverOptions;
+ var avatar = this.avatarsManager.getActiveAvatar() || this.avatarsManager.anonymousAvatarData();
+ this.miniProfileCtx = JSKW$Events.registerEventCallback(undefined, function(name, newSites) {
+ if (!self.serverOptions.extraFieldURL) return;
+ self.jskauth.setWebIdentities(JSKitLib.fmap(newSites, function(site) {
+ return self.jskauth.assembleIdentity(site.data[1], site.data[0], 'web');
+ }));
+ self.miniProfile.render("addAnotherSite");
+ self.miniProfile.render("siteLinksIcons", {"identities": self.jskauth.getIdentities()});
+ }, "profile_socialSitesUpdated");
+ var descriptors = {
+ "name": function(element) {
+ self.renderNameField(element, "js-kit-miniProfile-name-ipe", JSKitEPB.isExists());
+ },
+ "avatar": function(element) {
+ self.avatarsManager.assembleAvatarArea(element);
+ },
+ "logout": function(element) {
+ element.onclick = function() {
+ if (element.busy) return;
+ element.busy = true;
+ JSKitLib.text($JCL("loggingOut"), element, true);
+ self.jskauth.logout();
+ };
+ },
+ "logoutLink": function(element) { JSKitLib.text($JCL("menuLogout"), element); },
+ "logoutIcon": function(element) { JSKitLib.addPNG(element, "//cdn.js-kit.com/images/cross.png"); },
+ "addAnotherSite": function(element) {
+ return self.fromMenuLoggedIn();
+ }
+ };
+ var gfc = this.jskauth.getAuthIdentity("gfc");
+ if (gfc && gfc.params.site) gfc.params.domain = this.config.domain;
+ var data = {
+ "Name": this.getUserProperty("Name", $JCL("guest")),
+ "profile": so.profile,
+ "avatarData": avatar,
+ "identities": this.jskauth.getIdentities()
+ };
+ var config = {
+ "mode": "embedded",
+ "labels": $JCL,
+ "template": this.dtMiniProfileLeaveComment,
+ "uriDomain": this.uriDomain,
+ "uriAvatar": this.uriAvatar,
+ "cssPrefix": "js-kit-lcf-miniProfile",
+ "avatarSize": {"width": "64", "height": "64"},
+ "descriptors": descriptors,
+ "openFullProfile": function() { self.showProfile(target, data); },
+ "isNativeProfileDisabled": !self.serverOptions.showProfile
+ };
+ this.miniProfile = new JSKitMiniProfile(target, data, config);
+}
+
+JSCC.prototype.renderLeaveCommentForm = function() {
+ var s = this;
+ if (s.getSkin() != 'echo') {
+ if (s.TC["js-commentAvatar"]) {
+ JSKitLib.removeChildren(s.TC["js-commentAvatar"]);
+ s.avatarsManager.assembleAvatarArea(s.TC["js-commentAvatar"]);
+ }
+ return;
+ }
+ JSKitLib.fmap(["userInfoWrapper", "extraControlsMenuWrapper"], function(name) {
+ var element = s.TC["js-kit-lcf-" + name];
+ if (element && typeof(s[name]) == "function") s[name](element);
+ });
+}
+
+JSCC.prototype.userInfoWrapper = function(target) {
+ var template = this["dtCreateUserInfo" + (this.jskauth.isLogged() ? "" : "Non") + "Logged"];
+ JSKitLib.replaceChildren(target, JSKitLib.toDOM(template, "js-kit-lcf-", this).content);
+}
+
+JSCC.prototype.getRSSUrl = function() {
+ var config = this.config;
+ return this.serverOptions.customRSSLink
+ ? window.location.protocol + "//rss." + config.domain + "/comments" + config.path
+ : window.location.protocol + "//js-kit.com/rss/" + config.domain + config.path;
+}
+
+JSCC.prototype.openFollowPopup = function() {
+ var self = this;
+ var dialog, eventCtx;
+ if (window.JSKW$currentProfile) {
+ window.JSKW$currentProfile.hideProfile();
+ }
+ var notifyMode = self.serverOptions.notifyMode;
+ var followPanel = this.followPanelPopup = this.assembleFollowPanel("popup");
+ followPanel.get("rssThreadInput").value = this.getRSSUrl();
+ var closeDialog = function() {
+ dialog.close();
+ JSKW$Events.invalidateContext(eventCtx);
+ delete self.followPanelPopup;
+ };
+ var template = this.gtmpl(this.dtFollowPanelPopup);
+ var descriptors = {
+ "content": function() {
+ return followPanel.content;
+ },
+ "doneButton": function(element, dom) {
+ element.onclick = function() {
+ new JSRVC({
+ "uri": self.uriDomain + "/manage-email-subscription",
+ "ref": JSKitLib.getRef(self),
+ "target": self.target,
+ "request": {
+ "p": self.pathOverride,
+ "mode": self.serverOptions.notifyMode
+ }
+ });
+ element.value = $JCL("follow_subscriptionInProgress");
+ JSKitLib.fmap([
+ element,
+ dom.get("cancelButton")
+ ], function(control) {
+ if (control) control.disabled = true;
+ });
+ }
+ },
+ "cancelButton": function(element) {
+ element.onclick = function() {
+ closeDialog();
+ self.serverOptions.notifyMode = notifyMode;
+ };
+ },
+ "editNotifications": function(element) {
+ element.onclick = function() {
+ window.open(self.uriDomain + "/settings/pctl.cgi?site=" + self.config.domain);
+ }
+ }
+ };
+ var dom = JSKitLib.toDOM(template, "js-kit-follow-popup-", descriptors);
+ var config = {
+ "width": 450,
+ "height": 230,
+ "cssClass": "js-kit-follow-popup"
+ };
+ dialog = new JSKitModalDialog(dom.content, config);
+ dialog.open();
+ var handleServerResponse = function(eventName, data) {
+ self.serverOptions.profile = data.profile;
+ if (data.hasOwnProperty("mode")) {
+ self.serverOptions.notifyMode = data.mode;
+ }
+ self.updateFollowPanel(self.followPanel);
+ closeDialog();
+ }
+ eventCtx = JSKW$Events.registerEventCallback(undefined,
+ handleServerResponse, "JSKit_emailSubscription");
+}
+
+JSCC.prototype.updateFollowPanel = function(dom) {
+ var self = this;
+ JSKitLib.fmap(["noemail", "email", "anymails"], function(notifyMode) {
+ self.setInputState("radio",
+ dom.get("notifyOptionRadio-" + notifyMode),
+ self.serverOptions.notifyMode == notifyMode ? "checked" : "unchecked");
+ });
+}
+
+JSCC.prototype.assembleFollowPanel = function(postfix) {
+ var self = this;
+ var rssUrl = this.getRSSUrl();
+ var template = this.gtmpl(this.dtFollowPanel);
+ var getEmail = function(emptyEmailLabel) {
+ return self.extraFormFields["Email"] || emptyEmailLabel;
+ };
+ var descriptors = {
+ "rssIcon": function(element) {
+ JSKitLib.addPNG(element, "//cdn.js-kit.com/images/rss.png");
+ },
+ "rssThreadInput": function(element) {
+ element.title = rssUrl;
+ },
+ "rssThreadButton": function(element) {
+ element.onclick = function() { window.open(rssUrl); };
+ },
+ "emailAddress": function(element) {
+ JSKitLib.text(getEmail($JCL("follow_emptyEmail")), element, true);
+ },
+ "editProfileLink": function(element) {
+ element.onclick = function() {
+ var profile = window.JSKW$currentProfile;
+ if (profile && profile.isYours()) return;
+ setTimeout(function() {
+ self.showProfile(self.target,
+ {"profile": self.serverOptions.profile},
+ {"activeSection": "editProfile"});
+ }, 0);
+ JSKitLib.text($JCL("follow_openingProfile"), element, true);
+ JSKitLib.addClass(element, "js-kit-follow-openingProfile");
+ };
+ },
+ "emailIcon": function(element) {
+ JSKitLib.addPNG(element, "//cdn.js-kit.com/images/email.png");
+ }
+ };
+ JSKitLib.fmap(["noemail", "email", "anymails"], function(mode) {
+ var notifyOptionHandler = function(element, dom) {
+ var updateNotifyControlsLayout = function(previousMode) {
+ if (!getEmail()) {
+ var link = dom.get("emailAddress");
+ var getClass = function(notifyMode) {
+ return "js-kit-follow-activeNotifyMode-" + notifyMode;
+ };
+ if (previousMode) {
+ JSKitLib.removeClass(link, getClass(previousMode));
+ }
+ JSKitLib.addClass(link, getClass(mode));
+ }
+ self.updateFollowPanel(dom);
+ };
+ if (self.serverOptions.notifyMode == mode) {
+ updateNotifyControlsLayout();
+ }
+ element.onclick = function() {
+ var previousMode = self.serverOptions.notifyMode;
+ self.serverOptions.notifyMode = mode;
+ updateNotifyControlsLayout(previousMode);
+ };
+ };
+ descriptors["notifyOptionRadio-" + mode] = notifyOptionHandler;
+ descriptors["notifyOptionLabel-" + mode] = notifyOptionHandler;
+ });
+ return JSKitLib.toDOM(template, "js-kit-follow-", descriptors);
+}
+
+JSCC.prototype.extraControlsMenuWrapper = function(target) {
+ var self = this;
+ var container = this.TC["js-kit-lcf-extraControlsMenuContent"];
+ if (!container) return;
+ var tabs = [];
+ if (this.config.uploadImages) tabs.push({
+ "name": "images",
+ "icon": "//cdn.js-kit.com/images/picture_add.png",
+ "title": $JCL("addImgText"),
+ "content": function() {
+ var template =
+ '' +
+ '
{Label:addImagesSectionNotice}
' +
+ '
' +
+ '
' +
+ '
';
+ var dom = JSKitLib.toDOM(self.gtmpl(template), "js-kit-images-", {});
+ self.assembleImagesUploadForm(dom.get("form"), dom.get("list"));
+ return dom.content;
+ }
+ });
+ var panel = this.followPanel = this.assembleFollowPanel();
+ tabs.push({
+ "name": "follow",
+ "icon": "//cdn.js-kit.com/images/follow.png",
+ "title": $JCL("follow"),
+ "callbacks" : {
+ "onTabOpened": function() {
+ self.updateFollowPanel(panel);
+ setTimeout(function() {
+ panel.get("rssThreadInput").value = self.getRSSUrl();
+ }, 0);
+ },
+ "onTabClosed": function() {
+ panel.get("rssThreadInput").value = "";
+ }
+ },
+ "content": function() {
+ return panel.content;
+ }
+ });
+ var template =
+ '' +
+ '
' +
+ '
' +
+ '
' +
+ '
' +
+ '
';
+ var marker = function(element) {
+ JSKitLib.addPNG(element, "//cdn.js-kit.com/images/menu/vertical-menu-expand-marker.png");
+ };
+ this.extraControlsMenu = new JSTabsManager(tabs, {
+ "titles": target,
+ "content": container
+ }, {
+ "mode": "toggle",
+ "template": template,
+ "descriptors": {"expandMarker": marker}
+ });
+}
+
+JSCC.prototype.renderSubscribeEvents = function(subscribeEvents) {
+ var s = this;
+ if(subscribeEvents.error) {
+ alert(subscribeEvents.errorDescription);
+ return;
+ }
+ var appliedEvents = 0;
+ JSKitLib.fmap(subscribeEvents, function(subscribeEvent){
+ var item = s.jspg.getItemById(subscribeEvent.ID);
+ var f;
+ f = function(operation) {
+ if(operation=='add') {
+ if(!item) {
+ var cmtobj = subscribeEvent.content;
+ if(cmtobj.ParentID && !s.jspg.getItemById(cmtobj.ParentID)) return;
+ s.pause.visible = true;
+ s.renderPauseIndicator();
+ if(!s.pause.state) {
+ cmtobj.ID = subscribeEvent.ID;
+ if (s.serverOptions.clustering)
+ cmtobj.ParentID = JSFSearch.search(s.jspg.getItemsToDisplay(), cmtobj);
+ cmtobj.echoItem = true;
+ cmtobj.echoItemFirstTime = true;
+ cmtobj.imgs = s.parseImgData(cmtobj);
+ s.cmtInPlace(s.prepareCommentObj(cmtobj));
+ s.publishEvent('comment-added', {'cmtId': cmtobj.ID});
+ appliedEvents++;
+ }
+ } else {
+ f('edit');
+ }
+ }
+ if(s.pause.state) {
+ s.pause.queue.push(subscribeEvent);
+ if(operation=='add') {
+ s.renderPauseCounter();
+ }
+ return;
+ }
+ if(operation=='edit') {
+ if(item) {
+ var msgId = subscribeEvent.ID;
+ var cobj = s.objById[msgId];
+ JSKitLib.fmap(subscribeEvent.content,
+ function(v,k){
+ cobj[k] = v;
+ });
+ JSKW$Events.syncBroadcast("smileys-newCommentInDiv", cobj);
+ s.jspg.invalidateItemView(msgId);
+ if(s.jspg.getPageByItemId(msgId)==s.curPage-1){
+ var pageNo = s.curPage;
+ s.curPage = 0;
+ s.displayPage(pageNo);
+ }
+ JSKW$Events.syncBroadcast("comment-edited", s.jcaIndex, msgId);
+ appliedEvents++;
+ }
+ }
+ if(operation=='delete') {
+ if(item) {
+ s.postHandlerDelete(item.div);
+ appliedEvents++;
+ }
+ }
+ if(operation=='like_vote') {
+ if(item) {
+ var cobj = s.objById[subscribeEvent.ID];
+ cobj.likeInstance.vote(subscribeEvent.content.action, subscribeEvent.content);
+ }
+ }
+ }
+ f(subscribeEvent.operation);
+ });
+ if(appliedEvents > 0) {
+ s.reCalcPages();
+ s.controls.reveal();
+ }
+}
+
+JSCC.prototype.useEcho = function() {
+ return (this.getSkin() == 'echo') && this.serverOptions.echoLiveUpdates && !this.IM && !this.config.nolc && !this.config.moderate;
+}
+
+JSCC.prototype.useReplyThreadsCollapsing = function() {
+ return this.useEcho() && this.serverOptions.collapseReplyThreads;
+}
+
+JSCC.prototype.replaceCountTemplate = function(template, count) {
+ return template.replace(/{Count}/, count);
+}
+
+JSCC.prototype.constructPopupLink = function(count) {
+ var s = this;
+ var so = s.serverOptions;
+ var tmpl = s.utmpl['js-CommentsPopupLink'] || s.dtCommentsPopupLink;
+ var link = tmpl.replace(/{LinkLabel}/, s.constructCommentsLabel(count, so.countLabels));
+ link = s.replaceCountTemplate(link, count);
+ popupLink = JSKitLib.html(s.gtmpl(link));
+ JSKitLib.addEventHandler(popupLink, ['click'],
+ function(e) {
+ s.popComments();
+ JSKitLib.preventDefaultEvent(e);
+ });
+ return popupLink;
+}
+
+JSCC.prototype.drawCommentLink = function(count) {
+ var s = this;
+ if (s.popupLink) {
+ var oldPopupLink = s.popupLink;
+ s.popupLink = s.constructPopupLink(count);
+ s.target.parentNode.replaceChild(s.popupLink, oldPopupLink);
+ } else {
+ s.popupLink = s.constructPopupLink(count);
+ s.target.parentNode.insertBefore(s.popupLink, s.target);
+ JSKitLib.hide(s.target);
+ }
+}
+
+JSCC.prototype.constructCommentsLabel = function(c, labels) {
+ if (typeof window.JSKitCommentsCountFilter == 'function')
+ return JSKitCommentsCountFilter(c);
+ labels = labels || ["Comments", "Comments (1)", "Comments ({Count})"];
+ switch (c) {
+ case 0: return labels[0];
+ case 1: return labels[1];
+ default: return this.replaceCountTemplate(labels[2], c);
+ }
+}
+
+JSCC.prototype.popComments = function() {
+ var self = this;
+ var config = this.config;
+ switch (config['display-mode']) {
+ case 'ext-popup':
+ var wl = window.location;
+ var url = this.uriDomain + "/api/static/pop_comments?ref="
+ + encodeURIComponent(JSKitLib.getRef(self))
+ + "&title=" + encodeURIComponent(config['page-title']);
+
+ url += '&' + JSKitLib.fmap(config, function(v, k) {
+ if (v && !k.match(/^(domain|popup-width|popup-height|display-mode|disabled|noDataRequest)$/))
+ return k + "=" + encodeURIComponent(v);
+ }).join('&');
+
+ var params = 'width=' + config['popup-width'] + ", height=" + config['popup-height'] + ", status=yes, resizable=yes, scrollbars=yes";
+ var w = window.open(url, "js_kit_popup_" + self.jcaIndex, params);
+ w.focus();
+ break;
+ case 'int-popup':
+ var divc = this.target.cloneNode(false);
+ divc.jsk$initialized = false;
+ var title = this.config['popup-title'];
+ var popupWidget = new JSCC(divc, {'config': {'display-mode': 'inline'}});
+ var popupInstance = new JSKitUniversalContainer(divc,
+ {
+ 'mode': 'popup', 'title': self.replaceCountTemplate(title, '0'),
+ 'backdrop': 'yes', 'opacity': 0.4,
+ 'size': {'width': config['popup-width'], 'height': config['popup-height']},
+ 'cssPrefix': 'js-kit-popupComments',
+ 'whiteLabel': self.serverOptions.whitelabel
+ },
+ {
+ 'onContainerBeforeClose': function() {
+ if (window.JSKW$currentProfile) window.JSKW$currentProfile.hideProfile();
+ JSKW$Events.syncBroadcast("comments_closeControlsPopup");
+ popupWidget.CommentCancelled();
+ }
+ }
+ );
+ popupWidget.parentWidget = this;
+ popupWidget.popupInstance = popupInstance;
+ break;
+ }
+}
+
+JSCC.prototype.initAuth = function() {
+ var s = this;
+
+ var old_facebook = s.jskauth && s.jskauth.getAuthIdentity("facebook");
+
+ if (s.jskauth) s.jskauth.destroy();
+ s.jskauth = new JSKAuth({
+ ref: JSKitLib.getRef(s),
+ mode: "popup",
+ target: s.target,
+ identities: s.serverOptions.identities,
+ withBackdrop: "true"
+ });
+
+ var facebook = s.jskauth.getAuthIdentity("facebook");
+ if (facebook) {
+ JSKitFBSDK.prototype.detectXD(s.target);
+ }
+ if (old_facebook && old_facebook.user
+ && (!facebook || facebook.user != old_facebook.user)) {
+ new JSKitFBSDK(
+ JSKitLib.getRef(s),
+ old_facebook.params.app_id,
+ old_facebook.params.xd_receiver,
+ function() {
+ this.logout();
+ }
+ );
+ }
+}
+
+JSCC.prototype.updateConfigFromServer = function(so) {
+ var s = this;
+ JSKitLib.fmap({
+ 'display-mode': 'displayMode',
+ 'popup-title': 'popupTitle',
+ 'popup-width': 'popupWidth',
+ 'popup-height': 'popupHeight'
+ }, function(v, k) { s.config[k] = s.config[k] || so[v]; });
+ s.config.skin = s.hasOwnProperty("dtComment") ? s.config.skin : (s.config.skin || so.skin);
+ s.config['display-mode'] = s.config['display-mode'] || "inline";
+}
+
+JSCC.prototype.findRootParent = function(comment) {
+ return (comment && comment.ParentID) ?
+ this.findRootParent(this.objById[comment.ParentID]) : comment;
+}
+
+JSCC.prototype.assembleExpandRepliesMarker = function(comment) {
+ var self = this;
+ var template =
+ '';
+ var descriptors = {
+ "label": function() {
+ return JSKitLib.text($JCL("expandXMoreReplies", {"count": comment.extra.collapsedCmtsCount}));
+ },
+ "container": function(element) {
+ JSKitLib.addStyle(element, "margin-left: " + self.level4margin(1) + ";");
+ JSKitLib.setEventHandler(element, ["click"], function() {
+ var pageNo = self.curPage;
+ self.markCollapsedReplies(comment, false);
+ self.curPage = 0;
+ self.displayPage(pageNo);
+ });
+ }
+ };
+ return JSKitLib.toDOM(template, "js-kit-replies-expand-", descriptors).content;
+}
+
+JSCC.prototype.removeRepliesExpandMarker = function(comment) {
+ if (!comment.extra.expandMarker) return;
+ var marker = comment.extra.expandMarker;
+ if (JSKitLib.hasParentNode(marker)) {
+ marker.parentNode.removeChild(marker);
+ delete comment.extra.expandMarker;
+ }
+
+}
+
+JSCC.prototype.markCollapsedReplies = function(comment, collapse) {
+ if (!this.useReplyThreadsCollapsing()) return;
+ var self = this;
+ if (comment.ParentID) {
+ comment = this.findRootParent(comment);
+ }
+ if (!comment) return;
+ if (typeof(collapse) == "undefined") {
+ collapse = typeof(comment.extra.areRepliesCollapsed) == "undefined" ||
+ comment.extra.areRepliesCollapsed;
+ }
+ var threadWalk = function(cmt, callback, idx) {
+ if (!idx) idx = 0;
+ JSKitLib.fmap(cmt.thread, function(reply) {
+ idx++;
+ if (callback) callback(reply, idx);
+ idx = threadWalk(reply, callback, idx);
+ });
+ return idx;
+ };
+ var limits = {"chunk": 2, "full": 5};
+ var totalRepliesCount = threadWalk(comment);
+ threadWalk(comment, function(cmt, idx) {
+ cmt.extra.collapsed = collapse &&
+ totalRepliesCount > limits.full &&
+ idx - limits.chunk > 0 &&
+ idx + limits.chunk <= totalRepliesCount;
+ cmt.extra.cssClass = (collapse && totalRepliesCount - idx == limits.chunk - 1) ?
+ "jsk-ItemWrapper-borderless" : undefined;
+
+ if (cmt.extra.collapsed && cmt.ID == self.replyForId) {
+ cmt.extra.cssClass = "jsk-ItemWrapper-borderless";
+ cmt.extra.collapsed = false;
+ }
+
+ if (self.jspg) {
+ self.jspg.invalidateItemView(cmt.ID);
+ }
+ });
+ var collapsedCmtsCount = totalRepliesCount - limits.chunk*2;
+ comment.extra.collapsedCmtsCount = collapsedCmtsCount > 0 ? collapsedCmtsCount : 0;
+ comment.extra.areRepliesCollapsed = collapse;
+ this.removeRepliesExpandMarker(comment);
+}
+
+JSCC.prototype.newCount = function(count, so) {
+ var s = this;
+ s.serverOptions = so;
+ s.updateConfigFromServer(so);
+ s.drawCommentLink(count);
+ s.publishEvent('comments-count-updated', {'count': count});
+}
+
+/* Must be last to support Opera */
+JSCC.prototype.newData = function(arr, so) {
+ var s = this;
+
+ s.updateConfigFromServer(so);
+
+ if (s.config['display-mode'] == "inline") {
+ s.target.style.display = "block";
+ s.target.style.visibility = "visible";
+ }
+ JSKitLib.fmap(arr, function(obj) {
+ obj.Name = obj.Name || $JCL("guest");
+ });
+ s.serverOptions = so;
+ s.account = so.account || {};
+ s.searchString = so.srch;
+ s.adminMode = !!so.adminMode;
+ s.ownerMode = !!so.ownerMode;
+ s.inlineModeration = (s.adminMode && !s.config.moderate);
+
+ s.initAuth();
+
+ so.smiley = so.smiley || s.config.smiles == "yes";
+ s.config.uploadImages = so.uploadImages;
+ if (s.useEcho()) {
+ s.config.backwards = 'yes';
+ if (s.extraFormFields["Url"]) {
+ var identity = s.jskauth.assembleIdentity(s.extraFormFields["Url"], "home", "web");
+ s.jskauth.appendIdentity(identity);
+ }
+ }
+
+ if(so.TS)
+ this.serverDiffTS = so.TS - Math.round((new Date()).valueOf() / 1000);
+
+ var dims = {
+ "form": (s.getSkin() == 'echo') ? '64x64' : '96x96',
+ "thread": (s.config.nolc || s.getSkin() == 'echo') ? '48x48' : so.avatardim
+ };
+ s.avatarsManager = s.initAvatarsManager(dims.form);
+ s.maxAvatarDims = s.avatarsManager.splitAvatarDim(dims.thread);
+
+ JSKitLib.addClass(s.target, "js-CommentsSkin-" + (s.getSkin() || "wireframe"));
+
+ switch (s.config.skin) {
+ case "smoothgray":
+ s.navSym = JSKitLib.isIE() ? { "prev": '←', "next": '→'} : { "prev": '◀', "next": '▶' };
+ if(!s.hasOwnProperty("dtComment")) s.dtComment = JSCC.prototype.dtComment2;
+ s.dtCreate = JSCC.prototype.dtCreate2;
+ s.dtEditComment = JSCC.prototype.dtEditComment2;
+ break;
+ case "haloscan":
+ s.dtComment = JSCC.prototype.dtComment3;
+ s.dtCreate = JSCC.prototype.dtCreate3;
+ s.dtEditComment = JSCC.prototype.dtEditComment;
+ if (window.JK$HS$haloscan_style)
+ JSKitLib.addCss(window.JK$HS$haloscan_style, "comments-skin-haloscan-custom");
+ break;
+ case "echo":
+ s.dtComment = JSCC.prototype.dtCommentEcho;
+ s.dtCreate = JSCC.prototype.dtCreateEcho;
+ s.dtEditComment = JSCC.prototype.dtEditComment;
+ break;
+ }
+
+ if (so.smiley) {
+ s.smiles = {
+ "O:-)" : {file: 'innocent.gif', title: 'Innocent'},
+ ">:o": {file: 'yell.gif', title: 'Yell'},
+ ":)" : {file: 'smile.gif', title: 'Smile'},
+ ":-)" : {file: 'smile.gif', title: 'Smile'},
+ ";)" : {file: 'wink.gif', title: 'Wink'},
+ ";-)" : {file: 'wink.gif', title: 'Wink'},
+ ":'(" : {file: 'cry.gif', title: 'Cry'},
+ "8-)" : {file: 'cool.gif', title: 'Cool'},
+ ":(" : {file: 'frown.gif', title: 'Frown'},
+ ":-(" : {file: 'frown.gif', title: 'Frown'},
+ ":*" : {file: 'kiss.gif', title: 'Kiss'},
+ ":-*" : {file: 'kiss.gif', title: 'Kiss'},
+ ":-D" : {file: 'laughing.gif', title: 'Laughing'},
+ "=-O" : {file: 'surprised.gif', title: 'Surprised'},
+ "=-X" : {file: 'sealed.gif', title: 'Sealed'},
+ ":-[" : {file: 'embarassed.gif', title: 'Embarassed'},
+ ":-$" : {file: 'money-mouth.gif', title: 'Money mouth'},
+ ":-P" : {file: 'tongue-out.gif', title: 'Tongue out'},
+ ":-E" : {file: 'foot-in-mouth.gif', title: 'Foot in mouth'},
+ "*DONT_KNOW*" : {file: 'undecided.gif', title: 'Undecided'}
+ };
+ var f = function(v) { return v.replace(/([\W])/g,"\\$1"); };
+ JSKitLib.fmap(s.smiles, function(el, i) {
+ /* fix for case ">)" */
+ s.smiles[i].regexpText = new RegExp('(>|<)?' + f(i), 'g');
+ s.smiles[i].regexpTag = new RegExp(' ?' + f(s.smileTag(el)) + ' ?', 'g');
+ });
+ }
+ var cb = function(name, obj, jcaIndex) {
+ switch(name) {
+ case "smileys-onchangeCommentText":
+ if(so.smiley && obj && obj.Text) obj.Text = s.textSmiles2Graphical(obj.Text.replace(/&/g, "&"));
+ break;
+ case "smileys-beforePostNewComment":
+ if(so.smiley && obj && obj.value) obj.value = s.textSmiles2Graphical(obj.value, 1);
+ break;
+ case "smileys-loadCommentsWidget":
+ if (s.jcaIndex != jcaIndex) return;
+ /* no break needed !!! */
+ case "smileys-newCommentInDiv":
+ var needAutolink = (so.htmlMode || s.config.nolc);
+ if ((so.smiley || needAutolink) && obj && obj.Text) {
+ obj.Text = obj.Text.split(' ').join('');
+ if (needAutolink) {
+ var tags;
+ var tags2meta = function(t){tags = []; t = t.replace(/]*>.*?<\/a>|<.*?>/ig, function(m){tags.push(m); return ' %#HTML_TAG#% ';}); return t;};
+ var meta2tags = function(t){JSKitLib.map(function(v){t = t.replace(' %#HTML_TAG#% ', v);}, tags); return t;};
+ obj.Text = tags2meta(obj.Text);
+ obj.Text = obj.Text.replace(/((?:http|ftp|https):\/\/(?:[a-z0-9#:\/\;\?\-\.\+,@&=%!\*\'(){}\[\]$_|^~`](?!gt;|lt;))+)/ig, ' $1 ');
+ obj.Text = tags2meta(meta2tags(obj.Text));
+ }
+ obj.Text = obj.Text.replace(/&/g, '&');
+ if (so.smiley) obj.Text = s.textSmiles2Graphical(obj.Text);
+ if (needAutolink) {
+ obj.Text = meta2tags(obj.Text);
+ }
+ obj.Text = obj.Text.replace(/(]*)?([^&<>\s\/\-]{12})([^&<>\s\/\-]{12})/ig, function($0, $1, $2, $3){if($1)return $0; return $2+' '+$3;});
+ }
+ break;
+ }
+ }
+ var ctx = JSKW$Events.registerEventCallback(undefined, cb, "smileys-newCommentInDiv");
+ JSKW$Events.registerEventCallback(ctx, cb, "smileys-loadCommentsWidget");
+ JSKW$Events.registerEventCallback(ctx, cb, "smileys-beforePostNewComment");
+ JSKW$Events.registerEventCallback(ctx, cb, "smileys-onchangeCommentText");
+
+ if(so.req) {
+ s.config.sort = so.req.srt;
+ s.config.backwards = so.req.ord == 'desc' ? 'yes' : 'no';
+ s.config.thread = ((so.req.prs == 'flat') ? 'no' : 'yes');
+ }
+
+ s.gen++;
+ s.loading = false;
+
+ if(s.ctag != so.tag) {
+ s.objById = {};
+ if(s.jspg) s.invalidateJSPG();
+ }
+
+ var flat = (s.searchString) ? true : s.config.thread != 'yes';
+
+ var ttt = []; // top level thread
+ var newChildren = {};
+ var nc = 0;
+ JSKitLib.fmap(arr, function(obj) {
+ if(!obj.ID) return;
+ if(s.IM && obj.yours) obj.Name = 'Me';
+ if(flat) {
+ delete(obj.ParentID);
+ delete(obj.depth);
+ }
+ s.objById[obj.ID] = obj;
+ obj.extra = {};
+ obj.thread = [];
+ JSKW$Events.syncBroadcast("smileys-loadCommentsWidget", obj, s.jcaIndex);
+ obj.karma = new JSCCKarma(obj, s);
+ if(obj.status != 'D') nc++;
+ var prn = s.objById[obj.ParentID];
+ if(prn) {
+ if(!newChildren[obj.ParentID]) {
+ ttt.push(obj);
+ }
+ prn.thread.push(obj);
+ } else {
+ ttt.push(obj);
+ }
+ newChildren[obj.ID] = 1;
+ obj.imgs = s.parseImgData(obj);
+ });
+ if (s.useReplyThreadsCollapsing()) {
+ JSKitLib.fmap(ttt, function(cmt) {
+ s.markCollapsedReplies(cmt, true);
+ });
+ }
+ s.divPages(so, s.htmlPaginate(ttt));
+
+ if(this.IM) this.conversations = so.conversations;
+
+ s.ctag = so.tag;
+
+ if (so.wysiwyg) {
+ if (so.smiley) {
+ so.allowedHTMLTags.push('img/src', 'img/title', 'img/border', 'img/alt');
+ }
+ var attrsByTag = {};
+ JSKitLib.fmap(so.allowedHTMLTags, function(v) {
+ var p = v.split('/');
+ var tag = p[0] || p;
+ var attr = p[1];
+ if (!attrsByTag[tag]) {
+ attrsByTag[tag] = ["style"];
+ }
+ if (attr) {
+ attrsByTag[tag].push(attr);
+ }
+ });
+ var allowedTags = JSKitLib.fmap(attrsByTag, function(attrs, tag) {
+ return tag + (attrs.length ? '[' + attrs.join('|') + ']' : '');
+ }).join(',');
+ s.tmce = { foreign: true, cfg: {
+ document_base_url: '//cdn.js-kit.com',
+ convert_newlines_to_brs: true,
+ relative_urls: 0,
+ remove_script_host: 0,
+ uri_domain: '//cdn.js-kit.com',
+ width: '100%',
+ closePopups: function() {
+ var cns = document.body.childNodes;
+ var i = 0;
+ while(i < cns.length) {
+ if(cns[i].id && cns[i].id.match(/^mce_\d+$/) && cns[i].className.match(/clearlooks2/)) document.body.removeChild(cns[i]);
+ else i++;
+ }
+ },
+ bookMark: function() {
+ tinyMCE.settings.curBM = tinyMCE.activeEditor.selection.getBookmark();
+ },
+ mode: "none",
+ plugins: "inlinepopups" + (so.smiley?",emotions":"") + (so.media?",youtube":""),
+ theme: "advanced",
+ theme_advanced_buttons1:
+ "bold,italic,underline,|,undo,redo,link,unlink"
+ + (so.media?",youtube":"") + (so.smiley?",emotions":""),
+ theme_advanced_buttons2: "",
+ theme_advanced_buttons3: "",
+ theme_advanced_toolbar_location: "top",
+ theme_advanced_toolbar_align: "left",
+ valid_elements: allowedTags,
+ setup: function(ed) {
+ var setContent = function(ed, value, extra) {
+ if(JSKitLib.isIE()) {
+ ed.setContent(value, extra);
+ tinyMCE.execInstanceCommand(ed.id, 'selectall');
+ ed.selection.collapse(0);
+ } else {
+ ed.setContent('', extra);
+ ed.execCommand('mceInsertContent', false, value, extra);
+ }
+ };
+ JSKitLib.fmap(["onClick","onKeyUp"], function(ev) {
+ ed[ev].add(function(ed, e){
+ tinyMCE.settings.bookMark();
+ if (ev == 'onClick') {
+ JSKW$Events.syncBroadcast('JSMenu-CollapseAll');
+ JSKW$Events.syncBroadcast('miniProfile_collapseAll');
+ }
+ });
+ });
+ if (ed.getElement().smoothWysiwygLoading) {
+ ed.onBeforeRenderUI.add(function(ed, e) {
+ var el = ed.getElement();
+ el.jsk$cover.parentNode.replaceChild(el.jsk$wrapper, el.jsk$cover);
+ });
+ ed[JSKitLib.getBrowser() == 'gecko' ? 'onInit' : 'onPostRender'].add(function(ed, e) {
+ var el = ed.getElement();
+ JSKitLib.show(el.jsk$wrapper);
+ if (!el.jsk$nofocus && el.jsk$widget.config.backwards != 'yes')
+ el.jsk$widget.TC["js-Cmtsubmit"].scrollIntoView(false);
+ });
+ }
+ if(JSKitLib.getBrowser() == 'gecko') {
+ ed.onInit.add(function(ed, e) {
+ var d = ed.getDoc();
+ try {
+ d.designMode = 'on';
+ } catch(e) { ; }
+ });
+ }
+ if (ed.getElement().jsk$hasDefaultValue && (s.jskauth.loginStatus || !s.anonymousCmt)) {
+ ed.onInit.add(function(ed, e) {
+ var d = (JSKitLib.getBrowser() == 'gecko' ? ed.getDoc() : ed.getWin());
+ tinymce.dom.Event.add(d, 'focus', function(e) {
+ var el = ed.getElement();
+ if (!el.defaultRemoved) {
+ setContent(ed, '', {format: 'raw', skip_undo: true});
+ el.defaultRemoved = true;
+ }
+ tinyMCE.settings.auto_focus = el.id;
+ });
+ });
+ }
+ if (!so.smiley) return;
+ ed.onKeyUp.add(function(ed, e) {
+ var content = {Text: ed.getContent({format: 'raw'})};
+ JSKW$Events.syncBroadcast("smileys-onchangeCommentText", content);
+ if(tinyMCE.settings.smiley) {
+ setContent(ed, content.Text, {format: 'raw'});
+ }
+ });
+ }
+ }};
+ }
+
+ s.dataLoader(so, nc);
+
+ var showCD = function() {
+ if(so.ShowSavedCommentDialog)
+ so.ShowSavedCommentDialog(s);
+ }
+
+ if(so.wysiwyg && !window.tinyMCE) {
+ JSKitLib.preloadImg('//cdn.js-kit.com/images/loading.gif');
+ var inittmce = function() {
+ s.tmce.foreign = false;
+ s.tmce.cfg.plugins = "inlinepopups"+(so.smiley?",emotions":"")+(so.media?",youtube":""); // !inl-pop
+ s.tmce.cfg.strict_loading_mode = true;
+ tinyMCE.init(s.tmce.cfg);
+ showCD();
+ }
+ var oldcb = window.jsk$tmcecb;
+ if(oldcb) {
+ window.jsk$tmcecb = function() { if(oldcb) oldcb(); showCD(); };
+ } else {
+ window.jsk$tmcecb = inittmce;
+ JSKitLib.addScript('//cdn.js-kit.com/extra/tiny_mce/tmce.js', this.target);
+ }
+ } else {
+ showCD();
+ }
+
+ var f = s.onDataLoad;
+ if(f) { s.onDataLoad = null; setTimeout(f, 0); }
+ s.publishEvent('comments-data-loaded', {'count': so.pages.tc});
+
+ if(this.useEcho() && (!s.echoSubscribed)) {
+ var jsk$echo = jskEchoInit(JSKitLib.getRef(s), s.target);
+ var voidRenderer = function(rendererIdx) {
+ if(!jsk$echo.getRendererById(rendererIdx)) {
+ jsk$echo.existingRenderers.push({
+ id: rendererIdx,
+ content: function() {}
+ });
+ }
+ }
+ voidRenderer(0);
+ voidRenderer(1);
+ var request = {
+ p: s.config.path,
+ permalink: s.config.permalink
+ };
+ if (s.sourceFilter) request[s.sourceFilter.type] = s.sourceFilter.sources.list;
+ jsk$echo.subscribe([{
+ request: request,
+ callback: function() {
+ s.renderSubscribeEvents.apply(s, arguments)
+ }
+ }]);
+ s.echoSubscribed = true;
+ }
+}
diff --git a/english/courses/StatisticalAnalysis/w2/tutorial2.html b/english/courses/StatisticalAnalysis/w2/tutorial2.html
new file mode 100644
index 0000000..17a3957
--- /dev/null
+++ b/english/courses/StatisticalAnalysis/w2/tutorial2.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+Statistical Analysis
+
+
+
+
+
+
+ Şebnem Er
+
+
2nd Week's Tutorial
+Tutorial questions
+It is easy to estimate a confidence interval in R. Please examine this website .
+
+
+
\ No newline at end of file
diff --git a/english/courses/StatisticalAnalysis/w3/W3_ConfidenceIntervalProportion.docx b/english/courses/StatisticalAnalysis/w3/W3_ConfidenceIntervalProportion.docx
new file mode 100644
index 0000000..a30a564
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w3/W3_ConfidenceIntervalProportion.docx differ
diff --git a/english/courses/StatisticalAnalysis/w3/W3_ConfidenceIntervalProportion.pdf b/english/courses/StatisticalAnalysis/w3/W3_ConfidenceIntervalProportion.pdf
new file mode 100644
index 0000000..da2eb62
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w3/W3_ConfidenceIntervalProportion.pdf differ
diff --git a/english/courses/StatisticalAnalysis/w3/W3_ConfidenceIntervalProportionSolutions.xlsx b/english/courses/StatisticalAnalysis/w3/W3_ConfidenceIntervalProportionSolutions.xlsx
new file mode 100644
index 0000000..2276219
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w3/W3_ConfidenceIntervalProportionSolutions.xlsx differ
diff --git a/english/courses/StatisticalAnalysis/w3/tutorial3.html b/english/courses/StatisticalAnalysis/w3/tutorial3.html
new file mode 100644
index 0000000..18f3ded
--- /dev/null
+++ b/english/courses/StatisticalAnalysis/w3/tutorial3.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+Statistical Analysis
+
+
+
+
+
+
+Şebnem Er
+
+
3rd Week's Tutorial
+Tutorial questions for Confidence Interval of a Population Ratio
+If only you are willing to learn, not for passing the course, there are very nice examples on the web.
+It is easy to estimate a confidence interval in R. Please examine this website .
+
+
+
\ No newline at end of file
diff --git a/english/courses/StatisticalAnalysis/w4/W4_ConfidenceIntervalVariance_SampleSize.docx b/english/courses/StatisticalAnalysis/w4/W4_ConfidenceIntervalVariance_SampleSize.docx
new file mode 100644
index 0000000..1d8937b
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w4/W4_ConfidenceIntervalVariance_SampleSize.docx differ
diff --git a/english/courses/StatisticalAnalysis/w4/W4_ConfidenceIntervalVariance_SampleSize.pdf b/english/courses/StatisticalAnalysis/w4/W4_ConfidenceIntervalVariance_SampleSize.pdf
new file mode 100644
index 0000000..dfa585b
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w4/W4_ConfidenceIntervalVariance_SampleSize.pdf differ
diff --git a/english/courses/StatisticalAnalysis/w4/W4_ConfidenceIntervalVariance_SampleSize.xlsx b/english/courses/StatisticalAnalysis/w4/W4_ConfidenceIntervalVariance_SampleSize.xlsx
new file mode 100644
index 0000000..298aaef
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w4/W4_ConfidenceIntervalVariance_SampleSize.xlsx differ
diff --git a/english/courses/StatisticalAnalysis/w4/tutorial4.html b/english/courses/StatisticalAnalysis/w4/tutorial4.html
new file mode 100644
index 0000000..f665a14
--- /dev/null
+++ b/english/courses/StatisticalAnalysis/w4/tutorial4.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+Statistical Analysis
+
+
+
+
+
+
+Şebnem Er
+
+
4th Week's Tutorial
+Tutorial questions for Confidence Interval of a Population Variance and Sample Size Determination
+
+It is easy to estimate a confidence interval in R. Please examine this website .
+
+
+
\ No newline at end of file
diff --git a/english/courses/StatisticalAnalysis/w5/W5_TestMean.docx b/english/courses/StatisticalAnalysis/w5/W5_TestMean.docx
new file mode 100644
index 0000000..242d92c
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w5/W5_TestMean.docx differ
diff --git a/english/courses/StatisticalAnalysis/w5/W5_TestMean.pdf b/english/courses/StatisticalAnalysis/w5/W5_TestMean.pdf
new file mode 100644
index 0000000..3832094
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w5/W5_TestMean.pdf differ
diff --git a/english/courses/StatisticalAnalysis/w5/chap08.pdf b/english/courses/StatisticalAnalysis/w5/chap08.pdf
new file mode 100644
index 0000000..ae0df0b
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w5/chap08.pdf differ
diff --git a/english/courses/StatisticalAnalysis/w5/chap08.ppt b/english/courses/StatisticalAnalysis/w5/chap08.ppt
new file mode 100644
index 0000000..b3eaa29
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w5/chap08.ppt differ
diff --git a/english/courses/StatisticalAnalysis/w5/tutorial5.html b/english/courses/StatisticalAnalysis/w5/tutorial5.html
new file mode 100644
index 0000000..45de9bb
--- /dev/null
+++ b/english/courses/StatisticalAnalysis/w5/tutorial5.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+Statistical Analysis
+
+
+
+
+
+
+Şebnem Er
+
+
5th Week's Tutorial
+Test of Mean
+
+
+
+
\ No newline at end of file
diff --git a/english/courses/StatisticalAnalysis/w6/W6_Test2Means.docx b/english/courses/StatisticalAnalysis/w6/W6_Test2Means.docx
new file mode 100644
index 0000000..6d3fbd3
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w6/W6_Test2Means.docx differ
diff --git a/english/courses/StatisticalAnalysis/w6/W6_Test2Means.pdf b/english/courses/StatisticalAnalysis/w6/W6_Test2Means.pdf
new file mode 100644
index 0000000..4f46be1
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w6/W6_Test2Means.pdf differ
diff --git a/english/courses/StatisticalAnalysis/w6/chap09.pdf b/english/courses/StatisticalAnalysis/w6/chap09.pdf
new file mode 100644
index 0000000..5b9b836
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w6/chap09.pdf differ
diff --git a/english/courses/StatisticalAnalysis/w6/chap09.ppt b/english/courses/StatisticalAnalysis/w6/chap09.ppt
new file mode 100644
index 0000000..875cccf
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w6/chap09.ppt differ
diff --git a/english/courses/StatisticalAnalysis/w6/tutorial6.html b/english/courses/StatisticalAnalysis/w6/tutorial6.html
new file mode 100644
index 0000000..b9daf93
--- /dev/null
+++ b/english/courses/StatisticalAnalysis/w6/tutorial6.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+Statistical Analysis
+
+
+
+
+
+
+Şebnem Er
+
+
6th Week's Tutorial
+Test of 2 Population Means
+
+
+
+
\ No newline at end of file
diff --git a/english/courses/StatisticalAnalysis/w7/W7_TestMoreThan2Pop.doc b/english/courses/StatisticalAnalysis/w7/W7_TestMoreThan2Pop.doc
new file mode 100644
index 0000000..48c5e79
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w7/W7_TestMoreThan2Pop.doc differ
diff --git a/english/courses/StatisticalAnalysis/w7/W7_TestMoreThan2Pop.pdf b/english/courses/StatisticalAnalysis/w7/W7_TestMoreThan2Pop.pdf
new file mode 100644
index 0000000..42ffc3f
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w7/W7_TestMoreThan2Pop.pdf differ
diff --git a/english/courses/StatisticalAnalysis/w7/chap11.pdf b/english/courses/StatisticalAnalysis/w7/chap11.pdf
new file mode 100644
index 0000000..aebc922
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w7/chap11.pdf differ
diff --git a/english/courses/StatisticalAnalysis/w7/chap11.ppt b/english/courses/StatisticalAnalysis/w7/chap11.ppt
new file mode 100644
index 0000000..1b36974
Binary files /dev/null and b/english/courses/StatisticalAnalysis/w7/chap11.ppt differ
diff --git a/english/courses/StatisticalAnalysis/w7/tutorial7.html b/english/courses/StatisticalAnalysis/w7/tutorial7.html
new file mode 100644
index 0000000..448ea95
--- /dev/null
+++ b/english/courses/StatisticalAnalysis/w7/tutorial7.html
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+Statistical Analysis
+
+
+
+
+
+
+Şebnem Er
+
+
7th Week's Tutorial
+Test of More Than 2 Population Means - Analysis of Variance (ANOVA)
+
+
+
+
\ No newline at end of file
diff --git a/english/courses/analytics2020/Unsupervised-Learning.epub b/english/courses/analytics2020/Unsupervised-Learning.epub
new file mode 100644
index 0000000..3d5297b
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning.epub differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning.html b/english/courses/analytics2020/Unsupervised-Learning.html
new file mode 100644
index 0000000..3d2dc1b
--- /dev/null
+++ b/english/courses/analytics2020/Unsupervised-Learning.html
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+ Unsupervised Learning Methods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/english/courses/analytics2020/Unsupervised-Learning.pdf b/english/courses/analytics2020/Unsupervised-Learning.pdf
new file mode 100644
index 0000000..f9994b1
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning.pdf differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning.tex b/english/courses/analytics2020/Unsupervised-Learning.tex
new file mode 100644
index 0000000..57c1bc8
--- /dev/null
+++ b/english/courses/analytics2020/Unsupervised-Learning.tex
@@ -0,0 +1,702 @@
+% Options for packages loaded elsewhere
+\PassOptionsToPackage{unicode}{hyperref}
+\PassOptionsToPackage{hyphens}{url}
+%
+\documentclass[
+]{book}
+\usepackage{lmodern}
+\usepackage{amssymb,amsmath}
+\usepackage{ifxetex,ifluatex}
+\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
+ \usepackage[T1]{fontenc}
+ \usepackage[utf8]{inputenc}
+ \usepackage{textcomp} % provide euro and other symbols
+\else % if luatex or xetex
+ \usepackage{unicode-math}
+ \defaultfontfeatures{Scale=MatchLowercase}
+ \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
+\fi
+% Use upquote if available, for straight quotes in verbatim environments
+\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
+\IfFileExists{microtype.sty}{% use microtype if available
+ \usepackage[]{microtype}
+ \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
+}{}
+\makeatletter
+\@ifundefined{KOMAClassName}{% if non-KOMA class
+ \IfFileExists{parskip.sty}{%
+ \usepackage{parskip}
+ }{% else
+ \setlength{\parindent}{0pt}
+ \setlength{\parskip}{6pt plus 2pt minus 1pt}}
+}{% if KOMA class
+ \KOMAoptions{parskip=half}}
+\makeatother
+\usepackage{xcolor}
+\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
+\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}}
+\hypersetup{
+ pdftitle={Unsupervised Learning Methods},
+ pdfauthor={Dr Sebnem Er},
+ hidelinks,
+ pdfcreator={LaTeX via pandoc}}
+\urlstyle{same} % disable monospaced font for URLs
+\usepackage{color}
+\usepackage{fancyvrb}
+\newcommand{\VerbBar}{|}
+\newcommand{\VERB}{\Verb[commandchars=\\\{\}]}
+\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
+% Add ',fontsize=\small' for more characters per line
+\usepackage{framed}
+\definecolor{shadecolor}{RGB}{248,248,248}
+\newenvironment{Shaded}{\begin{snugshade}}{\end{snugshade}}
+\newcommand{\AlertTok}[1]{\textcolor[rgb]{0.94,0.16,0.16}{#1}}
+\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
+\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.77,0.63,0.00}{#1}}
+\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.00,0.00,0.81}{#1}}
+\newcommand{\BuiltInTok}[1]{#1}
+\newcommand{\CharTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
+\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textit{#1}}}
+\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
+\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.00,0.00,0.00}{#1}}
+\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{\textbf{#1}}}
+\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{#1}}
+\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.00,0.00,0.81}{#1}}
+\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
+\newcommand{\ErrorTok}[1]{\textcolor[rgb]{0.64,0.00,0.00}{\textbf{#1}}}
+\newcommand{\ExtensionTok}[1]{#1}
+\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.00,0.00,0.81}{#1}}
+\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.00,0.00,0.00}{#1}}
+\newcommand{\ImportTok}[1]{#1}
+\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
+\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.13,0.29,0.53}{\textbf{#1}}}
+\newcommand{\NormalTok}[1]{#1}
+\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.81,0.36,0.00}{\textbf{#1}}}
+\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{#1}}
+\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textit{#1}}}
+\newcommand{\RegionMarkerTok}[1]{#1}
+\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.00,0.00,0.00}{#1}}
+\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
+\newcommand{\StringTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
+\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.00,0.00,0.00}{#1}}
+\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.31,0.60,0.02}{#1}}
+\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.56,0.35,0.01}{\textbf{\textit{#1}}}}
+\usepackage{longtable,booktabs}
+% Correct order of tables after \paragraph or \subparagraph
+\usepackage{etoolbox}
+\makeatletter
+\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}
+\makeatother
+% Allow footnotes in longtable head/foot
+\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}}
+\makesavenoteenv{longtable}
+\usepackage{graphicx,grffile}
+\makeatletter
+\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}
+\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}
+\makeatother
+% Scale images if necessary, so that they will not overflow the page
+% margins by default, and it is still possible to overwrite the defaults
+% using explicit options in \includegraphics[width, height, ...]{}
+\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}
+% Set default figure placement to htbp
+\makeatletter
+\def\fps@figure{htbp}
+\makeatother
+\setlength{\emergencystretch}{3em} % prevent overfull lines
+\providecommand{\tightlist}{%
+ \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
+\setcounter{secnumdepth}{5}
+\usepackage{booktabs}
+\usepackage{amsthm}
+\makeatletter
+\def\thm@space@setup{%
+ \thm@preskip=8pt plus 2pt minus 4pt
+ \thm@postskip=\thm@preskip
+}
+\makeatother
+\usepackage[]{natbib}
+\bibliographystyle{apalike}
+
+\title{Unsupervised Learning Methods}
+\author{Dr Sebnem Er}
+\date{2020-10-02}
+
+\begin{document}
+\maketitle
+
+{
+\setcounter{tocdepth}{1}
+\tableofcontents
+}
+\hypertarget{introduction}{%
+\chapter{Introduction}\label{introduction}}
+
+This book will guide you through the R codes for the following Unsupervised Learning methods:
+
+\begin{itemize}
+\tightlist
+\item
+ Association Rules
+\item
+ Cluster Analysis
+\item
+ Self Organising Maps
+\end{itemize}
+
+The chapters will be made available on Tuesdays when we start a new topic. So please update your browser to access the codes for the relevant chapter.
+
+\hypertarget{association-rules}{%
+\chapter{Association Rules}\label{association-rules}}
+
+\hypertarget{prerequisites}{%
+\section{Prerequisites}\label{prerequisites}}
+
+You need to have the following R packages installed and recalled into your library:
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{library}\NormalTok{(datasets)}
+\KeywordTok{library}\NormalTok{(grid)}
+\KeywordTok{library}\NormalTok{(tidyverse)}
+\KeywordTok{library}\NormalTok{(readxl)}
+\KeywordTok{library}\NormalTok{(knitr)}
+\KeywordTok{library}\NormalTok{(ggplot2)}
+\KeywordTok{library}\NormalTok{(lubridate)}
+\KeywordTok{library}\NormalTok{(arules)}
+\KeywordTok{library}\NormalTok{(arulesViz)}
+\KeywordTok{library}\NormalTok{(plyr)}
+\end{Highlighting}
+\end{Shaded}
+
+\hypertarget{the-groceries-dataset}{%
+\section{The Groceries Dataset}\label{the-groceries-dataset}}
+
+We shall mine Groceries dataset for association rules using the Apriori Algorithm. The Groceries dataset can be loaded from R. The steps for doing so are shown below. Note that you will only be able to load the data set once the package \texttt{arules} has been loaded into R. The Groceries dataset contains a collection of receipts with each line representing 1 receipt and the items purchased. Each line is called a transaction and each column in a row represents an item.
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{data}\NormalTok{(Groceries)}
+\KeywordTok{summary}\NormalTok{(Groceries)}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## transactions as itemMatrix in sparse format with
+## 9835 rows (elements/itemsets/transactions) and
+## 169 columns (items) and a density of 0.02609146
+##
+## most frequent items:
+## whole milk other vegetables rolls/buns soda
+## 2513 1903 1809 1715
+## yogurt (Other)
+## 1372 34055
+##
+## element (itemset/transaction) length distribution:
+## sizes
+## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+## 2159 1643 1299 1005 855 645 545 438 350 246 182 117 78 77 55 46
+## 17 18 19 20 21 22 23 24 26 27 28 29 32
+## 29 14 14 9 11 4 6 1 1 1 1 3 1
+##
+## Min. 1st Qu. Median Mean 3rd Qu. Max.
+## 1.000 2.000 3.000 4.409 6.000 32.000
+##
+## includes extended item information - examples:
+## labels level2 level1
+## 1 frankfurter sausage meat and sausage
+## 2 sausage sausage meat and sausage
+## 3 liver loaf sausage meat and sausage
+\end{verbatim}
+
+As you can see, the data is in ``transactions'' format with a density of 0.0261 (check slides to remember what this value means). There are 9835 transactions with 169 distinct items that can be bought in this database (\(D\)).
+
+The summary function also provides the distribution of number items per transaction and the most popular items.
+
+Now let us examine the first 3 transactions in \(D\).
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{inspect}\NormalTok{(}\KeywordTok{head}\NormalTok{(Groceries, }\DecValTok{3}\NormalTok{))}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## items
+## [1] {citrus fruit,
+## semi-finished bread,
+## margarine,
+## ready soups}
+## [2] {tropical fruit,
+## yogurt,
+## coffee}
+## [3] {whole milk}
+\end{verbatim}
+
+The first customer bought {\{citrus fruit,semi-finished bread,margarine,ready soups\}}, whereas the third customer bought only {\{whole milk\}}.
+
+We can also find how many items each transaction contains, for the first 10 transactions:
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{head}\NormalTok{(}\KeywordTok{size}\NormalTok{(Groceries), }\DecValTok{10}\NormalTok{)}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## [1] 4 3 1 4 4 5 1 5 1 2
+\end{verbatim}
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{hist}\NormalTok{(}\KeywordTok{size}\NormalTok{(Groceries), }\DataTypeTok{main =} \StringTok{"Distribution of the number of items purchased"}\NormalTok{, }\DataTypeTok{xlab =} \StringTok{"Number of items"}\NormalTok{, }\DataTypeTok{ylab=}\StringTok{"Number of Transactions"}\NormalTok{)}
+\end{Highlighting}
+\end{Shaded}
+
+\includegraphics{Unsupervised-Learning_files/figure-latex/unnamed-chunk-4-1.pdf}
+
+As it is clear, the distribution of the number of items is skewed to right, clearly most transactions inlcude fewer number of items, only very few have more than 10 items purchased together.
+
+\hypertarget{support-count-item-frequencies-and-item-frequency-plot}{%
+\section{Support Count (Item Frequencies) and Item Frequency Plot}\label{support-count-item-frequencies-and-item-frequency-plot}}
+
+We can check the support count (\(freq(A)\)) for the top 25 products with the following R code:
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\NormalTok{itemSupportCount =}\StringTok{ }\KeywordTok{itemFrequency}\NormalTok{(Groceries, }\DataTypeTok{type =} \StringTok{"absolute"}\NormalTok{) }\CommentTok{# obtain the counts for individual items}
+\NormalTok{itemSupportCount =}\StringTok{ }\KeywordTok{sort}\NormalTok{(itemSupportCount, }\DataTypeTok{decreasing =} \OtherTok{TRUE}\NormalTok{) }\CommentTok{# sort the counts in descending order}
+\KeywordTok{head}\NormalTok{(itemSupportCount, }\DecValTok{25}\NormalTok{) }\CommentTok{# check the support count for the top 25 items}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## whole milk other vegetables rolls/buns
+## 2513 1903 1809
+## soda yogurt bottled water
+## 1715 1372 1087
+## root vegetables tropical fruit shopping bags
+## 1072 1032 969
+## sausage pastry citrus fruit
+## 924 875 814
+## bottled beer newspapers canned beer
+## 792 785 764
+## pip fruit fruit/vegetable juice whipped/sour cream
+## 744 711 705
+## brown bread domestic eggs frankfurter
+## 638 624 580
+## margarine coffee pork
+## 576 571 567
+## butter
+## 545
+\end{verbatim}
+
+We can also plot the support count, it is possible to change the colours of the bars as well.
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{itemFrequencyPlot}\NormalTok{(Groceries, }\DataTypeTok{topN =} \DecValTok{25}\NormalTok{, }\DataTypeTok{type=}\StringTok{"absolute"}\NormalTok{)}
+\end{Highlighting}
+\end{Shaded}
+
+\includegraphics{Unsupervised-Learning_files/figure-latex/unnamed-chunk-6-1.pdf}
+
+We can see that top purchased product is \{whole milk\} and it appears in 2513 transactions out of 9835. Therefore the support count for \{whole milk\} is 2513.
+
+\hypertarget{support}{%
+\section{Support}\label{support}}
+
+Remember the support (\(S(A)\)) is calculated as follows:
+
+\[S(A)=\frac{\texttt{freq({A})}}{n}\]
+The support for \{whole milk\} would be
+
+\[S(\texttt{{whole milk}})=\frac{\texttt{freq({whole milk})}}{n}=\frac{2513}{9835}=25.55\%\]
+
+It is possible to obtain this information with the same code as shown previously by simply replacing \(\texttt{type="absolute"}\) with the \(\texttt{type="relative"}\) option:
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\NormalTok{itemSupport =}\StringTok{ }\KeywordTok{itemFrequency}\NormalTok{(Groceries, }\DataTypeTok{type =} \StringTok{"relative"}\NormalTok{) }\CommentTok{# obtain the counts for individual items}
+\NormalTok{itemSupport =}\StringTok{ }\KeywordTok{sort}\NormalTok{(itemSupport, }\DataTypeTok{decreasing =} \OtherTok{TRUE}\NormalTok{) }\CommentTok{# sort the counts in descending order}
+\KeywordTok{head}\NormalTok{(itemSupport, }\DecValTok{25}\NormalTok{) }\CommentTok{# check the support count for the top 25 items}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## whole milk other vegetables rolls/buns
+## 0.25551601 0.19349263 0.18393493
+## soda yogurt bottled water
+## 0.17437722 0.13950178 0.11052364
+## root vegetables tropical fruit shopping bags
+## 0.10899847 0.10493137 0.09852567
+## sausage pastry citrus fruit
+## 0.09395018 0.08896797 0.08276563
+## bottled beer newspapers canned beer
+## 0.08052872 0.07981698 0.07768175
+## pip fruit fruit/vegetable juice whipped/sour cream
+## 0.07564820 0.07229283 0.07168277
+## brown bread domestic eggs frankfurter
+## 0.06487036 0.06344687 0.05897306
+## margarine coffee pork
+## 0.05856634 0.05805796 0.05765125
+## butter
+## 0.05541434
+\end{verbatim}
+
+We can also plot the support.
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{itemFrequencyPlot}\NormalTok{(Groceries, }\DataTypeTok{topN =} \DecValTok{25}\NormalTok{, }\DataTypeTok{type=}\StringTok{"relative"}\NormalTok{)}
+\end{Highlighting}
+\end{Shaded}
+
+\includegraphics{Unsupervised-Learning_files/figure-latex/unnamed-chunk-8-1.pdf}
+
+Note that the maximum support is low. To ensure that the top 25 frequent items are included in the analysis the minimum support would have to be less than 0.10! (\(10\%\)) Suppose we set the minimum support to 0.001 and minimum confidence to 0.8. We can mine some rules by executing the following R code:
+
+\hypertarget{rule-generation-with-apriori-algorithm}{%
+\section{Rule Generation with Apriori Algorithm}\label{rule-generation-with-apriori-algorithm}}
+
+\begin{itemize}
+\item
+ We are going to use the Apriori algorithm within the \(\texttt{arules}\) library to mine frequent itemsets and association rules..
+\item
+ Assume that we want to generate all the rules that satisfy the support threshold of \(0.1\%\) and confidence threshold of \(80\%\), then we need to enter \(\texttt{supp=0.001}\) and \(\texttt{conf=0.8}\) values in the \(\texttt{apriori()}\) function. If you want stronger rules, you can increase the value of \(\texttt{conf}\) and for more extended rules give higher value to \(\texttt{maxlen}\).
+\item
+ It might be desirable to sort the rules according either confidence or support, here we chose sorting according to confidence in a descending manner.
+\item
+ Finally we can examine the rules using \(\texttt{summary()}\) function.
+\end{itemize}
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\NormalTok{rules <-}\StringTok{ }\KeywordTok{apriori}\NormalTok{(Groceries, }\DataTypeTok{parameter =} \KeywordTok{list}\NormalTok{(}\DataTypeTok{supp=}\FloatTok{0.001}\NormalTok{, }\DataTypeTok{conf=}\FloatTok{0.8}\NormalTok{))}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## Apriori
+##
+## Parameter specification:
+## confidence minval smax arem aval originalSupport maxtime support minlen
+## 0.8 0.1 1 none FALSE TRUE 5 0.001 1
+## maxlen target ext
+## 10 rules TRUE
+##
+## Algorithmic control:
+## filter tree heap memopt load sort verbose
+## 0.1 TRUE TRUE FALSE TRUE 2 TRUE
+##
+## Absolute minimum support count: 9
+##
+## set item appearances ...[0 item(s)] done [0.00s].
+## set transactions ...[169 item(s), 9835 transaction(s)] done [0.03s].
+## sorting and recoding items ... [157 item(s)] done [0.00s].
+## creating transaction tree ... done [0.00s].
+## checking subsets of size 1 2 3 4 5 6 done [0.02s].
+## writing ... [410 rule(s)] done [0.00s].
+## creating S4 object ... done [0.00s].
+\end{verbatim}
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\NormalTok{rules <-}\StringTok{ }\KeywordTok{sort}\NormalTok{(rules, }\DataTypeTok{by=}\StringTok{'confidence'}\NormalTok{, }\DataTypeTok{decreasing =} \OtherTok{TRUE}\NormalTok{)}
+\KeywordTok{summary}\NormalTok{(rules)}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## set of 410 rules
+##
+## rule length distribution (lhs + rhs):sizes
+## 3 4 5 6
+## 29 229 140 12
+##
+## Min. 1st Qu. Median Mean 3rd Qu. Max.
+## 3.000 4.000 4.000 4.329 5.000 6.000
+##
+## summary of quality measures:
+## support confidence coverage lift
+## Min. :0.001017 Min. :0.8000 Min. :0.001017 Min. : 3.131
+## 1st Qu.:0.001017 1st Qu.:0.8333 1st Qu.:0.001220 1st Qu.: 3.312
+## Median :0.001220 Median :0.8462 Median :0.001322 Median : 3.588
+## Mean :0.001247 Mean :0.8663 Mean :0.001449 Mean : 3.951
+## 3rd Qu.:0.001322 3rd Qu.:0.9091 3rd Qu.:0.001627 3rd Qu.: 4.341
+## Max. :0.003152 Max. :1.0000 Max. :0.003559 Max. :11.235
+## count
+## Min. :10.00
+## 1st Qu.:10.00
+## Median :12.00
+## Mean :12.27
+## 3rd Qu.:13.00
+## Max. :31.00
+##
+## mining info:
+## data ntransactions support confidence
+## Groceries 9835 0.001 0.8
+\end{verbatim}
+
+In this output we are provided with the following information:
+
+\begin{itemize}
+\tightlist
+\item
+ There are 410 rules based on 0.001 support and 0.8 confidence thresholds.
+\item
+ The distribution of the number of items in each rule (rule length distribution): Most rules are 4 items long.
+\end{itemize}
+
+We need use the \(\texttt{inspect()}\) function to see the actual rules.
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{inspect}\NormalTok{(rules[}\DecValTok{1}\OperatorTok{:}\DecValTok{5}\NormalTok{])}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## lhs rhs support confidence coverage lift count
+## [1] {rice,
+## sugar} => {whole milk} 0.001220132 1 0.001220132 3.913649 12
+## [2] {canned fish,
+## hygiene articles} => {whole milk} 0.001118454 1 0.001118454 3.913649 11
+## [3] {root vegetables,
+## butter,
+## rice} => {whole milk} 0.001016777 1 0.001016777 3.913649 10
+## [4] {root vegetables,
+## whipped/sour cream,
+## flour} => {whole milk} 0.001728521 1 0.001728521 3.913649 17
+## [5] {butter,
+## soft cheese,
+## domestic eggs} => {whole milk} 0.001016777 1 0.001016777 3.913649 10
+\end{verbatim}
+
+If we look at the confidence we see that for the top 5 rules it is \(1\), this indicates \(100\%\) confidence:
+
+\begin{itemize}
+\item
+ \(100\%\) customers who bought ``\{rice, sugar\}'' end up buying ``\{whole milk\}'' as well.
+\item
+ \(100\%\) customers who bought ``\{canned fish, hygiene articles\}'' end up buying ``\{whole milk\}'' as well.
+\end{itemize}
+
+In the following section we will look at visualizing the rules.
+
+\hypertarget{visualisation-of-the-rules}{%
+\subsection{Visualisation of the Rules}\label{visualisation-of-the-rules}}
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\NormalTok{topRules <-}\StringTok{ }\NormalTok{rules[}\DecValTok{1}\OperatorTok{:}\DecValTok{10}\NormalTok{]}
+\KeywordTok{plot}\NormalTok{(topRules)}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## To reduce overplotting, jitter is added! Use jitter = 0 to prevent jitter.
+\end{verbatim}
+
+\includegraphics{Unsupervised-Learning_files/figure-latex/unnamed-chunk-11-1.pdf}
+
+The scatter plot of support and confidence of the top ten rules shows us that high confidence rules have low support values.
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{plot}\NormalTok{(rules)}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## To reduce overplotting, jitter is added! Use jitter = 0 to prevent jitter.
+\end{verbatim}
+
+\includegraphics{Unsupervised-Learning_files/figure-latex/unnamed-chunk-12-1.pdf}
+
+In the following section we will look at removing redundant rules.
+
+\hypertarget{removing-redundant-rules}{%
+\subsection{Removing redundant rules}\label{removing-redundant-rules}}
+
+You may want to remove rules that are subsets of larger rules. Use the code below to remove such rules:
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\NormalTok{subset.rules <-}\StringTok{ }\KeywordTok{which}\NormalTok{(}\KeywordTok{colSums}\NormalTok{(}\KeywordTok{is.subset}\NormalTok{(rules, rules)) }\OperatorTok{>}\StringTok{ }\DecValTok{1}\NormalTok{) }\CommentTok{# get subset rules in vector}
+\CommentTok{# is.subset() determines if elements of one vector contain all the elements of other}
+\KeywordTok{length}\NormalTok{(subset.rules)}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## [1] 91
+\end{verbatim}
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\NormalTok{subset.rules <-}\StringTok{ }\NormalTok{rules[}\OperatorTok{-}\NormalTok{subset.rules] }\CommentTok{# remove subset rules.}
+\end{Highlighting}
+\end{Shaded}
+
+\hypertarget{finding-rules-related-to-given-items}{%
+\subsection{Finding rules related to given items}\label{finding-rules-related-to-given-items}}
+
+In the case of specific product in interest, either as a precedent (LHS) or as a consequent (RHS) in the rule, you need to set the ``\(\texttt{appearance=}\)'' parameter in the apriori rule generating function:
+
+Let us say we are interested in those transactions that end up in buying ``root vegetables'':
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\NormalTok{rveg.rules <-}\StringTok{ }\KeywordTok{apriori}\NormalTok{(Groceries, }\DataTypeTok{parameter =} \KeywordTok{list}\NormalTok{(}\DataTypeTok{supp=}\FloatTok{0.001}\NormalTok{, }\DataTypeTok{conf=}\FloatTok{0.8}\NormalTok{),}\DataTypeTok{appearance =} \KeywordTok{list}\NormalTok{(}\DataTypeTok{default=}\StringTok{"lhs"}\NormalTok{,}\DataTypeTok{rhs=}\StringTok{"root vegetables"}\NormalTok{))}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## Apriori
+##
+## Parameter specification:
+## confidence minval smax arem aval originalSupport maxtime support minlen
+## 0.8 0.1 1 none FALSE TRUE 5 0.001 1
+## maxlen target ext
+## 10 rules TRUE
+##
+## Algorithmic control:
+## filter tree heap memopt load sort verbose
+## 0.1 TRUE TRUE FALSE TRUE 2 TRUE
+##
+## Absolute minimum support count: 9
+##
+## set item appearances ...[1 item(s)] done [0.00s].
+## set transactions ...[169 item(s), 9835 transaction(s)] done [0.01s].
+## sorting and recoding items ... [157 item(s)] done [0.00s].
+## creating transaction tree ... done [0.01s].
+## checking subsets of size 1 2 3 4 5 6 done [0.03s].
+## writing ... [5 rule(s)] done [0.00s].
+## creating S4 object ... done [0.00s].
+\end{verbatim}
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{inspect}\NormalTok{(}\KeywordTok{head}\NormalTok{(rveg.rules))}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## lhs rhs support confidence coverage lift count
+## [1] {other vegetables,
+## whole milk,
+## yogurt,
+## rice} => {root vegetables} 0.001321810 0.8666667 0.001525165 7.951182 13
+## [2] {tropical fruit,
+## other vegetables,
+## whole milk,
+## oil} => {root vegetables} 0.001321810 0.8666667 0.001525165 7.951182 13
+## [3] {beef,
+## citrus fruit,
+## tropical fruit,
+## other vegetables} => {root vegetables} 0.001016777 0.8333333 0.001220132 7.645367 10
+## [4] {citrus fruit,
+## other vegetables,
+## soda,
+## fruit/vegetable juice} => {root vegetables} 0.001016777 0.9090909 0.001118454 8.340400 10
+## [5] {tropical fruit,
+## other vegetables,
+## whole milk,
+## yogurt,
+## oil} => {root vegetables} 0.001016777 0.9090909 0.001118454 8.340400 10
+\end{verbatim}
+
+\hypertarget{using-your-own-dataset-stored-as-a-csv-file}{%
+\section{Using your own dataset stored as a csv file}\label{using-your-own-dataset-stored-as-a-csv-file}}
+
+You might want to use a dataset from a csv file. The format of this file should be as follows:
+
+\begin{itemize}
+\tightlist
+\item
+ Transactions in the rows (remember in our small example, we had 5 transactions.)
+\item
+ Items per transaction should be entered separately in different columns (items were A, B, C, D, E, and F)
+\end{itemize}
+
+\begin{figure}
+\centering
+\includegraphics{example.png}
+\caption{How the data looks like in csv format:}
+\end{figure}
+
+\begin{itemize}
+\tightlist
+\item
+ The data should be extracted using the \(\texttt{read.transactions()}\) function.
+\end{itemize}
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\NormalTok{slideExample <-}\StringTok{ }\KeywordTok{read.transactions}\NormalTok{(}\StringTok{'C:/Users/01438475/Google Drive/UCTcourses/Analytics/UnsupervisedLearning/Arules/example.csv'}\NormalTok{, }\DataTypeTok{format =} \StringTok{'basket'}\NormalTok{, }\DataTypeTok{sep=}\StringTok{','}\NormalTok{)}
+\NormalTok{slideExample}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## transactions in sparse format with
+## 5 transactions (rows) and
+## 6 items (columns)
+\end{verbatim}
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{inspect}\NormalTok{(}\KeywordTok{head}\NormalTok{(slideExample, }\DecValTok{6}\NormalTok{))}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## items
+## [1] {A,D}
+## [2] {A,B,C,E}
+## [3] {B,C,D,F}
+## [4] {A,B,C,D}
+## [5] {A,B,D,F}
+\end{verbatim}
+
+\begin{Shaded}
+\begin{Highlighting}[]
+\KeywordTok{size}\NormalTok{(}\KeywordTok{head}\NormalTok{(slideExample))}
+\end{Highlighting}
+\end{Shaded}
+
+\begin{verbatim}
+## [1] 2 4 4 4 4
+\end{verbatim}
+
+I will leave all the rest for you to obtain.
+
+\hypertarget{references}{%
+\section{References:}\label{references}}
+
+\begin{itemize}
+\tightlist
+\item
+ \href{http://www.rdatamining.com/examples/association-rules}{R and Data Mining}
+\item
+ \href{https://github.com/susanli2016/Data-Analysis-with-R/blob/master/Market_Basket_Analysis.Rmd}{Susan Li - MBA}
+\item
+ \href{https://www.datacamp.com/community/tutorials/market-basket-analysis-r}{Datacamp}
+\item
+ Dr Juwa Nyirenda's lecture notes
+\end{itemize}
+
+\hypertarget{cluster-analysis}{%
+\chapter{Cluster Analysis}\label{cluster-analysis}}
+
+For this section, please update your browser on the 13th of October Tuesday.
+
+\hypertarget{self-organising-maps}{%
+\chapter{Self Organising Maps}\label{self-organising-maps}}
+
+For this section, please update your browser on the 20th of October Tuesday.
+
+ \bibliography{book.bib,packages.bib}
+
+\end{document}
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-10-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-10-1.png
new file mode 100644
index 0000000..8b5a42d
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-10-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-11-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-11-1.png
new file mode 100644
index 0000000..3a5a150
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-11-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-12-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-12-1.png
new file mode 100644
index 0000000..31314ea
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-12-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-12-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-12-2.png
new file mode 100644
index 0000000..5beb0f7
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-12-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-12-3.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-12-3.png
new file mode 100644
index 0000000..788a1ed
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-12-3.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-13-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-13-1.png
new file mode 100644
index 0000000..9752916
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-13-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-13-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-13-2.png
new file mode 100644
index 0000000..dbb0f40
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-13-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-14-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-14-1.png
new file mode 100644
index 0000000..22f9bcb
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-14-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-15-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-15-1.png
new file mode 100644
index 0000000..0e01c24
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-15-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-16-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-16-1.png
new file mode 100644
index 0000000..d916c79
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-16-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-16-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-16-2.png
new file mode 100644
index 0000000..f4b247d
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-16-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-17-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-17-1.png
new file mode 100644
index 0000000..f212107
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-17-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-18-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-18-1.png
new file mode 100644
index 0000000..e37953b
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-18-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-19-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-19-1.png
new file mode 100644
index 0000000..d93ead1
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-19-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-24-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-24-1.png
new file mode 100644
index 0000000..956cb9d
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-24-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-25-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-25-1.png
new file mode 100644
index 0000000..956cb9d
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-25-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-26-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-26-1.png
new file mode 100644
index 0000000..7bc745b
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-26-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-27-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-27-1.png
new file mode 100644
index 0000000..4ce4cfe
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-27-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-27-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-27-2.png
new file mode 100644
index 0000000..d9515b4
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-27-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-27-3.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-27-3.png
new file mode 100644
index 0000000..22f5326
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-27-3.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-28-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-28-1.png
new file mode 100644
index 0000000..eba9305
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-28-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-28-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-28-2.png
new file mode 100644
index 0000000..d9515b4
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-28-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-28-3.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-28-3.png
new file mode 100644
index 0000000..22f5326
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-28-3.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-29-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-29-1.png
new file mode 100644
index 0000000..4ce4cfe
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-29-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-29-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-29-2.png
new file mode 100644
index 0000000..d9515b4
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-29-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-29-3.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-29-3.png
new file mode 100644
index 0000000..22f5326
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-29-3.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-30-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-30-1.png
new file mode 100644
index 0000000..9e0aa47
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-30-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-31-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-31-1.png
new file mode 100644
index 0000000..5a94688
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-31-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-31-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-31-2.png
new file mode 100644
index 0000000..dbb0f40
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-31-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-32-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-32-1.png
new file mode 100644
index 0000000..ca27d81
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-32-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-32-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-32-2.png
new file mode 100644
index 0000000..dbb0f40
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-32-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-33-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-33-1.png
new file mode 100644
index 0000000..ca89d56
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-33-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-33-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-33-2.png
new file mode 100644
index 0000000..dbb0f40
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-33-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-34-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-34-1.png
new file mode 100644
index 0000000..d916c79
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-34-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-34-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-34-2.png
new file mode 100644
index 0000000..f4b247d
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-34-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-35-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-35-1.png
new file mode 100644
index 0000000..cc494bf
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-35-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-35-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-35-2.png
new file mode 100644
index 0000000..f4b247d
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-35-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-36-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-36-1.png
new file mode 100644
index 0000000..54ed587
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-36-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-36-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-36-2.png
new file mode 100644
index 0000000..f4b247d
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-36-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-37-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-37-1.png
new file mode 100644
index 0000000..6630dac
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-37-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-38-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-38-1.png
new file mode 100644
index 0000000..1299c74
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-38-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-39-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-39-1.png
new file mode 100644
index 0000000..44c5a01
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-39-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-4-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-4-1.png
new file mode 100644
index 0000000..10b7344
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-4-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-40-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-40-1.png
new file mode 100644
index 0000000..87724b6
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-40-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-41-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-41-1.png
new file mode 100644
index 0000000..44c5a01
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-41-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-42-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-42-1.png
new file mode 100644
index 0000000..e8f1149
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-42-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-43-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-43-1.png
new file mode 100644
index 0000000..e8f1149
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-43-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-44-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-44-1.png
new file mode 100644
index 0000000..e8f1149
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-44-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-45-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-45-1.png
new file mode 100644
index 0000000..ffa3342
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-45-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-46-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-46-1.png
new file mode 100644
index 0000000..21899b6
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-46-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-46-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-46-2.png
new file mode 100644
index 0000000..5beb0f7
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-46-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-46-3.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-46-3.png
new file mode 100644
index 0000000..788a1ed
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-46-3.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-47-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-47-1.png
new file mode 100644
index 0000000..b60715c
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-47-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-48-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-48-1.png
new file mode 100644
index 0000000..ffa3342
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-48-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-49-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-49-1.png
new file mode 100644
index 0000000..5d02eb4
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-49-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-5-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-5-1.png
new file mode 100644
index 0000000..10b7344
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-5-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-50-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-50-1.png
new file mode 100644
index 0000000..8860815
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-50-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-51-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-51-1.png
new file mode 100644
index 0000000..5b0d113
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-51-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-51-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-51-2.png
new file mode 100644
index 0000000..5beb0f7
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-51-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-51-3.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-51-3.png
new file mode 100644
index 0000000..788a1ed
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-51-3.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-52-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-52-1.png
new file mode 100644
index 0000000..8860815
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-52-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-53-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-53-1.png
new file mode 100644
index 0000000..a38ce64
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-53-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-54-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-54-1.png
new file mode 100644
index 0000000..d7e16ec
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-54-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-54-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-54-2.png
new file mode 100644
index 0000000..5beb0f7
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-54-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-54-3.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-54-3.png
new file mode 100644
index 0000000..788a1ed
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-54-3.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-55-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-55-1.png
new file mode 100644
index 0000000..a38ce64
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-55-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-55-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-55-2.png
new file mode 100644
index 0000000..5beb0f7
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-55-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-55-3.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-55-3.png
new file mode 100644
index 0000000..788a1ed
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-55-3.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-56-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-56-1.png
new file mode 100644
index 0000000..d7e16ec
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-56-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-56-2.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-56-2.png
new file mode 100644
index 0000000..5beb0f7
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-56-2.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-56-3.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-56-3.png
new file mode 100644
index 0000000..788a1ed
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-56-3.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-6-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-6-1.png
new file mode 100644
index 0000000..1367cfd
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-6-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-7-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-7-1.png
new file mode 100644
index 0000000..1367cfd
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-7-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-8-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-8-1.png
new file mode 100644
index 0000000..8b5a42d
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-8-1.png differ
diff --git a/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-9-1.png b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-9-1.png
new file mode 100644
index 0000000..8b5a42d
Binary files /dev/null and b/english/courses/analytics2020/Unsupervised-Learning_files/figure-html/unnamed-chunk-9-1.png differ
diff --git a/english/courses/analytics2020/a-visualisation-map-weights-onto-colors.html b/english/courses/analytics2020/a-visualisation-map-weights-onto-colors.html
new file mode 100644
index 0000000..7b03163
--- /dev/null
+++ b/english/courses/analytics2020/a-visualisation-map-weights-onto-colors.html
@@ -0,0 +1,332 @@
+
+
+
+
+
+
+ Chapter 5 A. Visualisation - Map Weights onto Colors | Unsupervised Learning Methods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
A. Visualisation - Map Weights onto Colors
+
+
Vis - 1) Training Process
+
As the SOM training iterations progress, the distance from each node’s weights to the samples represented by that node is reduced. Ideally, this distance should reach a minimum plateau.
+This plot option shows the progress over time.
+If the curve is continually decreasing, more iterations are required.
+
plot (som_model, type= "changes" )
+
+
+
+
Vis - 2) Node Counts
+
The Kohonen packages allows us to visualise the count of how many samples are mapped to each node on the map.
+This metric can be used as a measure of map quality - ideally the sample distribution is relatively uniform.
+Large values in some map areas suggests that a larger map would be benificial.
+Empty nodes indicate that your map size is too big for the number of samples.
+Aim for at least 5-10 samples per node when choosing map size.
+
plot (som_model, type= "counts" )
+
+
+
+
Vis - 3) Neighbour Distance
+
plot (som_model, type= "dist.neighbours" )
+
+
+
+
Vis - 4) Codes / Weight vectors
+
plot (som_model, type= "codes" )
+
+
+
+
Vis - 5) Heatmaps
+
a=som_model$ codes[[1 ]]
+par (mfrow= c (4 ,4 ))
+for (i in 2 : 17 ){
+plot (som_model, type = "property" , property = a[,i-1 ], main= names (animals)[i])
+ }
+
+
+
## null device
+## 1
+
+
+
B. Clustering
+
data <- som_model$ codes[[1 ]]
+ wss <- (nrow (data)- 1 )* sum (apply (data,2 ,var))
+for (i in 2 : 15 ) {
+ wss[i] <- sum (kmeans (data, centers= i)$ withinss)
+ }
+plot (wss)
+
+
+
+
use hierarchical clustering to cluster the codebook vectors
+
som_cluster <- cutree (hclust (dist (som_model$ codes[[1 ]])), 7 )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/english/courses/analytics2020/applications.html b/english/courses/analytics2020/applications.html
new file mode 100644
index 0000000..8bba686
--- /dev/null
+++ b/english/courses/analytics2020/applications.html
@@ -0,0 +1,250 @@
+
+
+
+
+
+
+ Chapter 5 Applications | Unsupervised Learning Methods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Applications
+
Some significant applications are demonstrated in this chapter.
+
+
Example one
+
+
+
Example two
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/english/courses/analytics2020/association-rules.html b/english/courses/analytics2020/association-rules.html
new file mode 100644
index 0000000..6044e4d
--- /dev/null
+++ b/english/courses/analytics2020/association-rules.html
@@ -0,0 +1,574 @@
+
+
+
+
+
+
+ Chapter 2 Association Rules | Unsupervised Learning Methods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Association Rules
+
+
Prerequisites
+
You need to have the following R packages installed and recalled into your library:
+
library (datasets)
+library (grid)
+library (tidyverse)
+library (readxl)
+library (knitr)
+library (ggplot2)
+library (lubridate)
+library (arules)
+library (arulesViz)
+library (plyr)
+
+
+
The Groceries Dataset
+
We shall mine Groceries dataset for association rules using the Apriori Algorithm. The Groceries dataset can be loaded from R. The steps for doing so are shown below. Note that you will only be able to load the data set once the package arules has been loaded into R. The Groceries dataset contains a collection of receipts with each line representing 1 receipt and the items purchased. Each line is called a transaction and each column in a row represents an item.
+
data (Groceries)
+summary (Groceries)
+
## transactions as itemMatrix in sparse format with
+## 9835 rows (elements/itemsets/transactions) and
+## 169 columns (items) and a density of 0.02609146
+##
+## most frequent items:
+## whole milk other vegetables rolls/buns soda
+## 2513 1903 1809 1715
+## yogurt (Other)
+## 1372 34055
+##
+## element (itemset/transaction) length distribution:
+## sizes
+## 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+## 2159 1643 1299 1005 855 645 545 438 350 246 182 117 78 77 55 46
+## 17 18 19 20 21 22 23 24 26 27 28 29 32
+## 29 14 14 9 11 4 6 1 1 1 1 3 1
+##
+## Min. 1st Qu. Median Mean 3rd Qu. Max.
+## 1.000 2.000 3.000 4.409 6.000 32.000
+##
+## includes extended item information - examples:
+## labels level2 level1
+## 1 frankfurter sausage meat and sausage
+## 2 sausage sausage meat and sausage
+## 3 liver loaf sausage meat and sausage
+
As you can see, the data is in “transactions” format with a density of 0.0261 (check slides to remember what this value means). There are 9835 transactions with 169 distinct items that can be bought in this database (\(D\) ).
+
The summary function also provides the distribution of number items per transaction and the most popular items.
+
Now let us examine the first 3 transactions in \(D\) .
+
inspect (head (Groceries, 3 ))
+
## items
+## [1] {citrus fruit,
+## semi-finished bread,
+## margarine,
+## ready soups}
+## [2] {tropical fruit,
+## yogurt,
+## coffee}
+## [3] {whole milk}
+
The first customer bought {citrus fruit,semi-finished bread,margarine,ready soups} , whereas the third customer bought only {whole milk} .
+
We can also find how many items each transaction contains, for the first 10 transactions:
+
head (size (Groceries), 10 )
+
## [1] 4 3 1 4 4 5 1 5 1 2
+
hist (size (Groceries), main = "Distribution of the number of items purchased" , xlab = "Number of items" , ylab= "Number of Transactions" )
+
+
As it is clear, the distribution of the number of items is skewed to right, clearly most transactions inlcude fewer number of items, only very few have more than 10 items purchased together.
+
+
+
Support Count (Item Frequencies) and Item Frequency Plot
+
We can check the support count (\(freq(A)\) ) for the top 25 products with the following R code:
+
itemSupportCount = itemFrequency (Groceries, type = "absolute" ) # obtain the counts for individual items
+ itemSupportCount = sort (itemSupportCount, decreasing = TRUE ) # sort the counts in descending order
+head (itemSupportCount, 25 ) # check the support count for the top 25 items
+
## whole milk other vegetables rolls/buns
+## 2513 1903 1809
+## soda yogurt bottled water
+## 1715 1372 1087
+## root vegetables tropical fruit shopping bags
+## 1072 1032 969
+## sausage pastry citrus fruit
+## 924 875 814
+## bottled beer newspapers canned beer
+## 792 785 764
+## pip fruit fruit/vegetable juice whipped/sour cream
+## 744 711 705
+## brown bread domestic eggs frankfurter
+## 638 624 580
+## margarine coffee pork
+## 576 571 567
+## butter
+## 545
+
We can also plot the support count, it is possible to change the colours of the bars as well.
+
itemFrequencyPlot (Groceries, topN = 25 , type= "absolute" )
+
+
We can see that top purchased product is {whole milk} and it appears in 2513 transactions out of 9835. Therefore the support count for {whole milk} is 2513.
+
+
+
Support
+
Remember the support (\(S(A)\) ) is calculated as follows:
+
\[S(A)=\frac{\texttt{freq({A})}}{n}\]
+The support for {whole milk} would be
+
\[S(\texttt{{whole milk}})=\frac{\texttt{freq({whole milk})}}{n}=\frac{2513}{9835}=25.55\%\]
+
It is possible to obtain this information with the same code as shown previously by simply replacing \(\texttt{type="absolute"}\) with the \(\texttt{type="relative"}\) option:
+
itemSupport = itemFrequency (Groceries, type = "relative" ) # obtain the counts for individual items
+ itemSupport = sort (itemSupport, decreasing = TRUE ) # sort the counts in descending order
+head (itemSupport, 25 ) # check the support count for the top 25 items
+
## whole milk other vegetables rolls/buns
+## 0.25551601 0.19349263 0.18393493
+## soda yogurt bottled water
+## 0.17437722 0.13950178 0.11052364
+## root vegetables tropical fruit shopping bags
+## 0.10899847 0.10493137 0.09852567
+## sausage pastry citrus fruit
+## 0.09395018 0.08896797 0.08276563
+## bottled beer newspapers canned beer
+## 0.08052872 0.07981698 0.07768175
+## pip fruit fruit/vegetable juice whipped/sour cream
+## 0.07564820 0.07229283 0.07168277
+## brown bread domestic eggs frankfurter
+## 0.06487036 0.06344687 0.05897306
+## margarine coffee pork
+## 0.05856634 0.05805796 0.05765125
+## butter
+## 0.05541434
+
We can also plot the support.
+
itemFrequencyPlot (Groceries, topN = 25 , type= "relative" )
+
+
Note that the maximum support is low. To ensure that the top 25 frequent items are included in the analysis the minimum support would have to be less than 0.10! (\(10\%\) ) Suppose we set the minimum support to 0.001 and minimum confidence to 0.8. We can mine some rules by executing the following R code:
+
+
+
Rule Generation with Apriori Algorithm
+
+We are going to use the Apriori algorithm within the \(\texttt{arules}\) library to mine frequent itemsets and association rules..
+Assume that we want to generate all the rules that satisfy the support threshold of \(0.1\%\) and confidence threshold of \(80\%\) , then we need to enter \(\texttt{supp=0.001}\) and \(\texttt{conf=0.8}\) values in the \(\texttt{apriori()}\) function. If you want stronger rules, you can increase the value of \(\texttt{conf}\) and for more extended rules give higher value to \(\texttt{maxlen}\) .
+It might be desirable to sort the rules according either confidence or support, here we chose sorting according to confidence in a descending manner.
+Finally we can examine the rules using \(\texttt{summary()}\) function.
+
+
rules <- apriori (Groceries, parameter = list (supp= 0.001 , conf= 0.8 ))
+
## Apriori
+##
+## Parameter specification:
+## confidence minval smax arem aval originalSupport maxtime support minlen
+## 0.8 0.1 1 none FALSE TRUE 5 0.001 1
+## maxlen target ext
+## 10 rules TRUE
+##
+## Algorithmic control:
+## filter tree heap memopt load sort verbose
+## 0.1 TRUE TRUE FALSE TRUE 2 TRUE
+##
+## Absolute minimum support count: 9
+##
+## set item appearances ...[0 item(s)] done [0.00s].
+## set transactions ...[169 item(s), 9835 transaction(s)] done [0.00s].
+## sorting and recoding items ... [157 item(s)] done [0.00s].
+## creating transaction tree ... done [0.00s].
+## checking subsets of size 1 2 3 4 5 6 done [0.01s].
+## writing ... [410 rule(s)] done [0.00s].
+## creating S4 object ... done [0.00s].
+
rules <- sort (rules, by= 'confidence' , decreasing = TRUE )
+summary (rules)
+
## set of 410 rules
+##
+## rule length distribution (lhs + rhs):sizes
+## 3 4 5 6
+## 29 229 140 12
+##
+## Min. 1st Qu. Median Mean 3rd Qu. Max.
+## 3.000 4.000 4.000 4.329 5.000 6.000
+##
+## summary of quality measures:
+## support confidence coverage lift
+## Min. :0.001017 Min. :0.8000 Min. :0.001017 Min. : 3.131
+## 1st Qu.:0.001017 1st Qu.:0.8333 1st Qu.:0.001220 1st Qu.: 3.312
+## Median :0.001220 Median :0.8462 Median :0.001322 Median : 3.588
+## Mean :0.001247 Mean :0.8663 Mean :0.001449 Mean : 3.951
+## 3rd Qu.:0.001322 3rd Qu.:0.9091 3rd Qu.:0.001627 3rd Qu.: 4.341
+## Max. :0.003152 Max. :1.0000 Max. :0.003559 Max. :11.235
+## count
+## Min. :10.00
+## 1st Qu.:10.00
+## Median :12.00
+## Mean :12.27
+## 3rd Qu.:13.00
+## Max. :31.00
+##
+## mining info:
+## data ntransactions support confidence
+## Groceries 9835 0.001 0.8
+
In this output we are provided with the following information:
+
+There are 410 rules based on 0.001 support and 0.8 confidence thresholds.
+The distribution of the number of items in each rule (rule length distribution): Most rules are 4 items long.
+
+
We need use the \(\texttt{inspect()}\) function to see the actual rules.
+
+
## lhs rhs support confidence coverage lift count
+## [1] {rice,
+## sugar} => {whole milk} 0.001220132 1 0.001220132 3.913649 12
+## [2] {canned fish,
+## hygiene articles} => {whole milk} 0.001118454 1 0.001118454 3.913649 11
+## [3] {root vegetables,
+## butter,
+## rice} => {whole milk} 0.001016777 1 0.001016777 3.913649 10
+## [4] {root vegetables,
+## whipped/sour cream,
+## flour} => {whole milk} 0.001728521 1 0.001728521 3.913649 17
+## [5] {butter,
+## soft cheese,
+## domestic eggs} => {whole milk} 0.001016777 1 0.001016777 3.913649 10
+
If we look at the confidence we see that for the top 5 rules it is \(1\) , this indicates \(100\%\) confidence:
+
+\(100\%\) customers who bought “{rice, sugar}” end up buying “{whole milk}” as well.
+\(100\%\) customers who bought “{canned fish, hygiene articles}” end up buying “{whole milk}” as well.
+
+
In the following section we will look at visualizing the rules.
+
+
Visualisation of the Rules
+
topRules <- rules[1 : 10 ]
+plot (topRules)
+
## To reduce overplotting, jitter is added! Use jitter = 0 to prevent jitter.
+
+
The scatter plot of support and confidence of the top ten rules shows us that high confidence rules have low support values.
+
+
## To reduce overplotting, jitter is added! Use jitter = 0 to prevent jitter.
+
+
In the following section we will look at removing redundant rules.
+
+
+
Removing redundant rules
+
You may want to remove rules that are subsets of larger rules. Use the code below to remove such rules:
+
subset.rules <- which (colSums (is.subset (rules, rules)) > 1 ) # get subset rules in vector
+# is.subset() determines if elements of one vector contain all the elements of other
+length (subset.rules)
+
## [1] 91
+
subset.rules <- rules[- subset.rules] # remove subset rules.
+
+
+
+
+
Using your own dataset stored as a csv file
+
You might want to use a dataset from a csv file. The format of this file should be as follows:
+
+Transactions in the rows (remember in our small example, we had 5 transactions.)
+Items per transaction should be entered separately in different columns (items were A, B, C, D, E, and F)
+
+
+
+The data should be extracted using the \(\texttt{read.transactions()}\) function.
+
+
slideExample <- read.transactions ('C:/Users/01438475/Google Drive/UCTcourses/Analytics/UnsupervisedLearning/Arules/example.csv' , format = 'basket' , sep= ',' )
+ slideExample
+
## transactions in sparse format with
+## 5 transactions (rows) and
+## 6 items (columns)
+
inspect (head (slideExample, 6 ))
+
## items
+## [1] {A,D}
+## [2] {A,B,C,E}
+## [3] {B,C,D,F}
+## [4] {A,B,C,D}
+## [5] {A,B,D,F}
+
+
## [1] 2 4 4 4 4
+
I will leave all the rest for you to obtain.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/english/courses/analytics2020/bookdown-demo_files/figure-html/nice-fig-1.png b/english/courses/analytics2020/bookdown-demo_files/figure-html/nice-fig-1.png
new file mode 100644
index 0000000..344323b
Binary files /dev/null and b/english/courses/analytics2020/bookdown-demo_files/figure-html/nice-fig-1.png differ
diff --git a/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-14-1.png b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-14-1.png
new file mode 100644
index 0000000..80ef7eb
Binary files /dev/null and b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-14-1.png differ
diff --git a/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-17-1.png b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-17-1.png
new file mode 100644
index 0000000..92597bc
Binary files /dev/null and b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-17-1.png differ
diff --git a/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-18-1.png b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-18-1.png
new file mode 100644
index 0000000..fb6cae2
Binary files /dev/null and b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-18-1.png differ
diff --git a/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-19-1.png b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-19-1.png
new file mode 100644
index 0000000..d93ead1
Binary files /dev/null and b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-19-1.png differ
diff --git a/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-7-1.png b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-7-1.png
new file mode 100644
index 0000000..b436caa
Binary files /dev/null and b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-7-1.png differ
diff --git a/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-8-1.png b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-8-1.png
new file mode 100644
index 0000000..4ac4716
Binary files /dev/null and b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-8-1.png differ
diff --git a/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-9-1.png b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-9-1.png
new file mode 100644
index 0000000..3674e41
Binary files /dev/null and b/english/courses/analytics2020/bookdown-demo_files/figure-html/unnamed-chunk-9-1.png differ
diff --git a/english/courses/analytics2020/cluster-analysis.html b/english/courses/analytics2020/cluster-analysis.html
new file mode 100644
index 0000000..c416de0
--- /dev/null
+++ b/english/courses/analytics2020/cluster-analysis.html
@@ -0,0 +1,250 @@
+
+
+
+
+
+
+ Chapter 3 Cluster Analysis | Unsupervised Learning Methods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Cluster Analysis
+
For this section, please update your browser on the 13th of October Tuesday.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/english/courses/analytics2020/compute-pairewise-distance-matrices.html b/english/courses/analytics2020/compute-pairewise-distance-matrices.html
new file mode 100644
index 0000000..acea3c7
--- /dev/null
+++ b/english/courses/analytics2020/compute-pairewise-distance-matrices.html
@@ -0,0 +1,390 @@
+
+
+
+
+
+
+ Chapter 4 Compute pairewise distance matrices | Unsupervised Learning Methods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Compute pairewise distance matrices
+
dist.out <- dist (df, method = "euclidean" )
+
+
Single Linkage
+
+
+
Complete Linkage
+
hc <- hclust (dist.out, method = "complete" )
+
Visualization of hclust
+
plot (hc, labels = F,- 1 )
+rect.hclust (hc, k = 2 , border = 2 : 3 ) # Add rectangle around 3 groups
+
+
+
+
Centroid
+
+
+
Methods for determining number of clusters
+
+
Elbow method for k-means clustering
+
set.seed (123 )
+# Compute and plot wss for k = 2 to k = 15
+ k.max <- 15 # Maximal number of clusters
+ df.out <- df
+ wss <- sapply (1 : k.max,
+function (k){kmeans (df.out, k, nstart= 10 )$ tot.withinss})
+plot (1 : k.max, wss, type= "b" , pch = 19 , frame = FALSE , xlab= "Number of clusters K" , ylab= "Total within-clusters sum of squares" )
+abline (v = 3 , lty = 2 )
+
+
According to the elbow method, the optimal number of clusters suggested for the K-means algorithm is 3.
+
+
+
Average silhouette method for k-means clustering
+
k.max <- 15
+ data.out <- df
+ sil <- rep (0 , k.max)
+# Compute the average silhouette width for
+# k = 2 to k = 15
+for (i in 2 : k.max){
+ km.res <- kmeans (df.out, centers = i, nstart = 25 )
+ ss <- silhouette (km.res$ cluster, dist (df.out))
+ sil[i] <- mean (ss[, 3 ])
+ }
+
# Plot the average silhouette width
+plot (1 : k.max, sil, type = "b" , pch = 19 ,
+frame = FALSE , xlab = "Number of clusters k" )
+abline (v = which.max (sil), lty = 2 )
+
+
According to the silhouette method the optimal number of clusters suggested for the Kmeans algorithm is 2.
+
+
+
Average silhouette method for PAM clustering
+
#clusplot(pam.out, main = "Cluster plot, k = 2", color = TRUE)
+plot (pam.out)
+
+
These two components explain 86.75% of the point variability.
+
This table shows how to use the average silhouette width value:
+
Range of SC : Interpretation
+0.71-1.0 : A strong structure has been found
+0.51-0.70 : A reasonable structure has been found
+0.26-0.50 : The structure is weak and could be artificial
+< 0.25 : No substantial structure has been found
+
According to the table, the fit is weak.
+
+
+
Average silhouette method for hierarchical clustering
+
plot (silhouette (cutree (hc,2 ),dist.out))
+
+
Average silhouette width : 0.4
+
This table shows how to use the average silhouette width value:
+
Range of SC: Interpretation
+0.71-1.0 : A strong structure has been found
+0.51-0.70 : A reasonable structure has been found
+0.26-0.50 : The structure is weak and could be artificial
+< 0.25 : No substantial structure has been found
+
The result for hierarchical clustering is similar to that of PAM. The conclusion we can make is that fit is weak.
+
+
+
Gap Statistic for K means clustering
+
# Compute gap statistic
+ gap_stat <- clusGap (df, FUN = kmeans, nstart = 25 , K.max = 10 , B = 50 )
+# Print the result
+plot (gap_stat, frame = FALSE , xlab = "Number of clusters k" )
+abline (v = 4 , lty = 2 )
+
+
According to the Gap Statistic the ’optimal number of clusters chosen for the Kmeans algorithm is 4!
+
Using the NbClust package which uses a vote to chose the number of clusters.
+The following example determine the number of clusters using all statistics:
+
res.nb <- NbClust (df, distance = "euclidean" ,min.nc = 2 , max.nc
+ = 10 , method = "complete" , index = "all" )
+
+
## *** : The Hubert index is a graphical method of determining the number of clusters.
+## In the plot of Hubert index, we seek a significant knee that corresponds to a
+## significant increase of the value of the measure i.e the significant peak in Hubert
+## index second differences plot.
+##
+
+
## *** : The D index is a graphical method of determining the number of clusters.
+## In the plot of D index, we seek a significant knee (the significant peak in Dindex
+## second differences plot) that corresponds to a significant increase of the value of
+## the measure.
+##
+## *******************************************************************
+## * Among all indices:
+## * 9 proposed 2 as the best number of clusters
+## * 4 proposed 3 as the best number of clusters
+## * 6 proposed 4 as the best number of clusters
+## * 2 proposed 5 as the best number of clusters
+## * 1 proposed 8 as the best number of clusters
+## * 1 proposed 10 as the best number of clusters
+##
+## ***** Conclusion *****
+##
+## * According to the majority rule, the best number of clusters is 2
+##
+##
+## *******************************************************************
+
When all statistics in the NbClust package are allowed to vote, the majority (in this case 9 out of 23) propose
+that the ‘optimal’ number of clusters should be 2.
+
+
+
+
Clustering with CLARA.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/english/courses/analytics2020/example.png b/english/courses/analytics2020/example.png
new file mode 100644
index 0000000..8ff2711
Binary files /dev/null and b/english/courses/analytics2020/example.png differ
diff --git a/english/courses/analytics2020/final-words.html b/english/courses/analytics2020/final-words.html
new file mode 100644
index 0000000..050e27b
--- /dev/null
+++ b/english/courses/analytics2020/final-words.html
@@ -0,0 +1,244 @@
+
+
+
+
+
+
+ Chapter 6 Final Words | Unsupervised Learning Methods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Final Words
+
We have finished a nice book.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/english/courses/analytics2020/index.html b/english/courses/analytics2020/index.html
new file mode 100644
index 0000000..58fd285
--- /dev/null
+++ b/english/courses/analytics2020/index.html
@@ -0,0 +1,261 @@
+
+
+
+
+
+
+ Unsupervised Learning Methods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Introduction
+
This book will guide you through the R codes for the following Unsupervised Learning methods:
+
+Association Rules
+Cluster Analysis
+Self Organising Maps
+
+
The chapters will be made available on Tuesdays when we start a new topic. So please update your browser to access the codes for the relevant chapter.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/english/courses/analytics2020/intro.html b/english/courses/analytics2020/intro.html
new file mode 100644
index 0000000..e966d97
--- /dev/null
+++ b/english/courses/analytics2020/intro.html
@@ -0,0 +1,422 @@
+
+
+
+
+
+
+ Chapter 2 Introduction | Unsupervised Learning Methods
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Introduction
+
You can label chapter and section titles using {#label} after them, e.g., we can reference Chapter 2 . If you do not manually label them, there will be automatic labels anyway, e.g., Chapter 4 .
+
Figures and tables with captions will be placed in figure and table environments, respectively.
+
par (mar = c (4 , 4 , .1 , .1 ))
+plot (pressure, type = 'b' , pch = 19 )
+
+
Reference a figure by its code chunk label with the fig: prefix, e.g., see Figure 2.1 . Similarly, you can reference tables generated from knitr::kable(), e.g., see Table 2.1 .
+
knitr:: kable (
+ head (iris, 20 ), caption = 'Here is a nice table!' ,
+ booktabs = TRUE
+ )
+
+Table 2.1: Here is a nice table!
+
+
+
+
+
+5.1
+3.5
+1.4
+0.2
+setosa
+
+
+4.9
+3.0
+1.4
+0.2
+setosa
+
+
+4.7
+3.2
+1.3
+0.2
+setosa
+
+
+4.6
+3.1
+1.5
+0.2
+setosa
+
+
+5.0
+3.6
+1.4
+0.2
+setosa
+
+
+5.4
+3.9
+1.7
+0.4
+setosa
+
+
+4.6
+3.4
+1.4
+0.3
+setosa
+
+
+5.0
+3.4
+1.5
+0.2
+setosa
+
+
+4.4
+2.9
+1.4
+0.2
+setosa
+
+
+4.9
+3.1
+1.5
+0.1
+setosa
+
+
+5.4
+3.7
+1.5
+0.2
+setosa
+
+
+4.8
+3.4
+1.6
+0.2
+setosa
+
+
+4.8
+3.0
+1.4
+0.1
+setosa
+
+
+4.3
+3.0
+1.1
+0.1
+setosa
+
+
+5.8
+4.0
+1.2
+0.2
+setosa
+
+
+5.7
+4.4
+1.5
+0.4
+setosa
+
+
+5.4
+3.9
+1.3
+0.4
+setosa
+
+
+5.1
+3.5
+1.4
+0.3
+setosa
+
+
+5.7
+3.8
+1.7
+0.3
+setosa
+
+
+5.1
+3.8
+1.5
+0.3
+setosa
+
+
+
+
You can write citations, too. For example, we are using the bookdown package (Xie 2020 ) in this sample book, which was built on top of R Markdown and knitr (Xie 2015 ) .
+
+
+References
+
+
+
Xie, Yihui. 2015. Dynamic Documents with R and Knitr . 2nd ed. Boca Raton, Florida: Chapman; Hall/CRC. http://yihui.name/knitr/ .
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/english/courses/analytics2020/libs/accessible-code-block-0.0.1/empty-anchor.js b/english/courses/analytics2020/libs/accessible-code-block-0.0.1/empty-anchor.js
new file mode 100644
index 0000000..ca349fd
--- /dev/null
+++ b/english/courses/analytics2020/libs/accessible-code-block-0.0.1/empty-anchor.js
@@ -0,0 +1,15 @@
+// Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) -->
+// v0.0.1
+// Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020.
+
+document.addEventListener('DOMContentLoaded', function() {
+ const codeList = document.getElementsByClassName("sourceCode");
+ for (var i = 0; i < codeList.length; i++) {
+ var linkList = codeList[i].getElementsByTagName('a');
+ for (var j = 0; j < linkList.length; j++) {
+ if (linkList[j].innerHTML === "") {
+ linkList[j].setAttribute('aria-hidden', 'true');
+ }
+ }
+ }
+});
diff --git a/english/courses/analytics2020/libs/gitbook-2.6.7/css/fontawesome/fontawesome-webfont.ttf b/english/courses/analytics2020/libs/gitbook-2.6.7/css/fontawesome/fontawesome-webfont.ttf
new file mode 100644
index 0000000..35acda2
Binary files /dev/null and b/english/courses/analytics2020/libs/gitbook-2.6.7/css/fontawesome/fontawesome-webfont.ttf differ
diff --git a/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-bookdown.css b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-bookdown.css
new file mode 100644
index 0000000..8e5bb8a
--- /dev/null
+++ b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-bookdown.css
@@ -0,0 +1,99 @@
+.book .book-header h1 {
+ padding-left: 20px;
+ padding-right: 20px;
+}
+.book .book-header.fixed {
+ position: fixed;
+ right: 0;
+ top: 0;
+ left: 0;
+ border-bottom: 1px solid rgba(0,0,0,.07);
+}
+span.search-highlight {
+ background-color: #ffff88;
+}
+@media (min-width: 600px) {
+ .book.with-summary .book-header.fixed {
+ left: 300px;
+ }
+}
+@media (max-width: 1240px) {
+ .book .book-body.fixed {
+ top: 50px;
+ }
+ .book .book-body.fixed .body-inner {
+ top: auto;
+ }
+}
+@media (max-width: 600px) {
+ .book.with-summary .book-header.fixed {
+ left: calc(100% - 60px);
+ min-width: 300px;
+ }
+ .book.with-summary .book-body {
+ transform: none;
+ left: calc(100% - 60px);
+ min-width: 300px;
+ }
+ .book .book-body.fixed {
+ top: 0;
+ }
+}
+
+.book .book-body.fixed .body-inner {
+ top: 50px;
+}
+.book .book-body .page-wrapper .page-inner section.normal sub, .book .book-body .page-wrapper .page-inner section.normal sup {
+ font-size: 85%;
+}
+
+@media print {
+ .book .book-summary, .book .book-body .book-header, .fa {
+ display: none !important;
+ }
+ .book .book-body.fixed {
+ left: 0px;
+ }
+ .book .book-body,.book .book-body .body-inner, .book.with-summary {
+ overflow: visible !important;
+ }
+}
+.kable_wrapper {
+ border-spacing: 20px 0;
+ border-collapse: separate;
+ border: none;
+ margin: auto;
+}
+.kable_wrapper > tbody > tr > td {
+ vertical-align: top;
+}
+.book .book-body .page-wrapper .page-inner section.normal table tr.header {
+ border-top-width: 2px;
+}
+.book .book-body .page-wrapper .page-inner section.normal table tr:last-child td {
+ border-bottom-width: 2px;
+}
+.book .book-body .page-wrapper .page-inner section.normal table td, .book .book-body .page-wrapper .page-inner section.normal table th {
+ border-left: none;
+ border-right: none;
+}
+.book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr, .book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr > td {
+ border-top: none;
+}
+.book .book-body .page-wrapper .page-inner section.normal table.kable_wrapper > tbody > tr:last-child > td {
+ border-bottom: none;
+}
+
+div.theorem, div.lemma, div.corollary, div.proposition, div.conjecture {
+ font-style: italic;
+}
+span.theorem, span.lemma, span.corollary, span.proposition, span.conjecture {
+ font-style: normal;
+}
+div.proof:after {
+ content: "\25a2";
+ float: right;
+}
+.header-section-number {
+ padding-right: .5em;
+}
diff --git a/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-clipboard.css b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-clipboard.css
new file mode 100644
index 0000000..6844a70
--- /dev/null
+++ b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-clipboard.css
@@ -0,0 +1,18 @@
+div.sourceCode {
+ position: relative;
+}
+
+.copy-to-clipboard-button {
+ position: absolute;
+ right: 0;
+ top: 0;
+ visibility: hidden;
+}
+
+.copy-to-clipboard-button:focus {
+ outline: 0;
+}
+
+div.sourceCode:hover > .copy-to-clipboard-button {
+ visibility: visible;
+}
diff --git a/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-fontsettings.css b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-fontsettings.css
new file mode 100644
index 0000000..87236b4
--- /dev/null
+++ b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-fontsettings.css
@@ -0,0 +1,292 @@
+/*
+ * Theme 1
+ */
+.color-theme-1 .dropdown-menu {
+ background-color: #111111;
+ border-color: #7e888b;
+}
+.color-theme-1 .dropdown-menu .dropdown-caret .caret-inner {
+ border-bottom: 9px solid #111111;
+}
+.color-theme-1 .dropdown-menu .buttons {
+ border-color: #7e888b;
+}
+.color-theme-1 .dropdown-menu .button {
+ color: #afa790;
+}
+.color-theme-1 .dropdown-menu .button:hover {
+ color: #73553c;
+}
+/*
+ * Theme 2
+ */
+.color-theme-2 .dropdown-menu {
+ background-color: #2d3143;
+ border-color: #272a3a;
+}
+.color-theme-2 .dropdown-menu .dropdown-caret .caret-inner {
+ border-bottom: 9px solid #2d3143;
+}
+.color-theme-2 .dropdown-menu .buttons {
+ border-color: #272a3a;
+}
+.color-theme-2 .dropdown-menu .button {
+ color: #62677f;
+}
+.color-theme-2 .dropdown-menu .button:hover {
+ color: #f4f4f5;
+}
+.book .book-header .font-settings .font-enlarge {
+ line-height: 30px;
+ font-size: 1.4em;
+}
+.book .book-header .font-settings .font-reduce {
+ line-height: 30px;
+ font-size: 1em;
+}
+.book.color-theme-1 .book-body {
+ color: #704214;
+ background: #f3eacb;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section {
+ background: #f3eacb;
+}
+.book.color-theme-2 .book-body {
+ color: #bdcadb;
+ background: #1c1f2b;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section {
+ background: #1c1f2b;
+}
+.book.font-size-0 .book-body .page-inner section {
+ font-size: 1.2rem;
+}
+.book.font-size-1 .book-body .page-inner section {
+ font-size: 1.4rem;
+}
+.book.font-size-2 .book-body .page-inner section {
+ font-size: 1.6rem;
+}
+.book.font-size-3 .book-body .page-inner section {
+ font-size: 2.2rem;
+}
+.book.font-size-4 .book-body .page-inner section {
+ font-size: 4rem;
+}
+.book.font-family-0 {
+ font-family: Georgia, serif;
+}
+.book.font-family-1 {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal {
+ color: #704214;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal a {
+ color: inherit;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h3,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h4,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h5,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 {
+ color: inherit;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2 {
+ border-color: inherit;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 {
+ color: inherit;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal hr {
+ background-color: inherit;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal blockquote {
+ border-color: #c4b29f;
+ opacity: 0.9;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code {
+ background: #fdf6e3;
+ color: #657b83;
+ border-color: #f8df9c;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal .highlight {
+ background-color: inherit;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table th,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table td {
+ border-color: #f5d06c;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr {
+ color: inherit;
+ background-color: #fdf6e3;
+ border-color: #444444;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) {
+ background-color: #fbeecb;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal {
+ color: #bdcadb;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal a {
+ color: #3eb1d0;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h3,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h4,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h5,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 {
+ color: #fffffa;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2 {
+ border-color: #373b4e;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 {
+ color: #373b4e;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal hr {
+ background-color: #373b4e;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal blockquote {
+ border-color: #373b4e;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code {
+ color: #9dbed8;
+ background: #2d3143;
+ border-color: #2d3143;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal .highlight {
+ background-color: #282a39;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table th,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table td {
+ border-color: #3b3f54;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr {
+ color: #b6c2d2;
+ background-color: #2d3143;
+ border-color: #3b3f54;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) {
+ background-color: #35394b;
+}
+.book.color-theme-1 .book-header {
+ color: #afa790;
+ background: transparent;
+}
+.book.color-theme-1 .book-header .btn {
+ color: #afa790;
+}
+.book.color-theme-1 .book-header .btn:hover {
+ color: #73553c;
+ background: none;
+}
+.book.color-theme-1 .book-header h1 {
+ color: #704214;
+}
+.book.color-theme-2 .book-header {
+ color: #7e888b;
+ background: transparent;
+}
+.book.color-theme-2 .book-header .btn {
+ color: #3b3f54;
+}
+.book.color-theme-2 .book-header .btn:hover {
+ color: #fffff5;
+ background: none;
+}
+.book.color-theme-2 .book-header h1 {
+ color: #bdcadb;
+}
+.book.color-theme-1 .book-body .navigation {
+ color: #afa790;
+}
+.book.color-theme-1 .book-body .navigation:hover {
+ color: #73553c;
+}
+.book.color-theme-2 .book-body .navigation {
+ color: #383f52;
+}
+.book.color-theme-2 .book-body .navigation:hover {
+ color: #fffff5;
+}
+/*
+ * Theme 1
+ */
+.book.color-theme-1 .book-summary {
+ color: #afa790;
+ background: #111111;
+ border-right: 1px solid rgba(0, 0, 0, 0.07);
+}
+.book.color-theme-1 .book-summary .book-search {
+ background: transparent;
+}
+.book.color-theme-1 .book-summary .book-search input,
+.book.color-theme-1 .book-summary .book-search input:focus {
+ border: 1px solid transparent;
+}
+.book.color-theme-1 .book-summary ul.summary li.divider {
+ background: #7e888b;
+ box-shadow: none;
+}
+.book.color-theme-1 .book-summary ul.summary li i.fa-check {
+ color: #33cc33;
+}
+.book.color-theme-1 .book-summary ul.summary li.done > a {
+ color: #877f6a;
+}
+.book.color-theme-1 .book-summary ul.summary li a,
+.book.color-theme-1 .book-summary ul.summary li span {
+ color: #877f6a;
+ background: transparent;
+ font-weight: normal;
+}
+.book.color-theme-1 .book-summary ul.summary li.active > a,
+.book.color-theme-1 .book-summary ul.summary li a:hover {
+ color: #704214;
+ background: transparent;
+ font-weight: normal;
+}
+/*
+ * Theme 2
+ */
+.book.color-theme-2 .book-summary {
+ color: #bcc1d2;
+ background: #2d3143;
+ border-right: none;
+}
+.book.color-theme-2 .book-summary .book-search {
+ background: transparent;
+}
+.book.color-theme-2 .book-summary .book-search input,
+.book.color-theme-2 .book-summary .book-search input:focus {
+ border: 1px solid transparent;
+}
+.book.color-theme-2 .book-summary ul.summary li.divider {
+ background: #272a3a;
+ box-shadow: none;
+}
+.book.color-theme-2 .book-summary ul.summary li i.fa-check {
+ color: #33cc33;
+}
+.book.color-theme-2 .book-summary ul.summary li.done > a {
+ color: #62687f;
+}
+.book.color-theme-2 .book-summary ul.summary li a,
+.book.color-theme-2 .book-summary ul.summary li span {
+ color: #c1c6d7;
+ background: transparent;
+ font-weight: 600;
+}
+.book.color-theme-2 .book-summary ul.summary li.active > a,
+.book.color-theme-2 .book-summary ul.summary li a:hover {
+ color: #f4f4f5;
+ background: #252737;
+ font-weight: 600;
+}
diff --git a/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-highlight.css b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-highlight.css
new file mode 100644
index 0000000..2aabd3d
--- /dev/null
+++ b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-highlight.css
@@ -0,0 +1,426 @@
+.book .book-body .page-wrapper .page-inner section.normal pre,
+.book .book-body .page-wrapper .page-inner section.normal code {
+ /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
+ /* Tomorrow Comment */
+ /* Tomorrow Red */
+ /* Tomorrow Orange */
+ /* Tomorrow Yellow */
+ /* Tomorrow Green */
+ /* Tomorrow Aqua */
+ /* Tomorrow Blue */
+ /* Tomorrow Purple */
+}
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-comment,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-comment,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-title {
+ color: #8e908c;
+}
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-variable,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-variable,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-attribute,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-tag,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-tag,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-regexp,
+.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-constant,
+.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-constant,
+.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-tag .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-tag .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-pi,
+.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-pi,
+.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-doctype,
+.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-doctype,
+.book .book-body .page-wrapper .page-inner section.normal pre .html .hljs-doctype,
+.book .book-body .page-wrapper .page-inner section.normal code .html .hljs-doctype,
+.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-id,
+.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-id,
+.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-class,
+.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-class,
+.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo,
+.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo {
+ color: #c82829;
+}
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-number,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-number,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-pragma,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-built_in,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-literal,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-literal,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-params,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-params,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-constant,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-constant {
+ color: #f5871f;
+}
+.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-class .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-class .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-rules .hljs-attribute,
+.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-rules .hljs-attribute {
+ color: #eab700;
+}
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-string,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-string,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-value,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-value,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-inheritance,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-inheritance,
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-header,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-header,
+.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-symbol,
+.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-symbol,
+.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata,
+.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata {
+ color: #718c00;
+}
+.book .book-body .page-wrapper .page-inner section.normal pre .css .hljs-hexcolor,
+.book .book-body .page-wrapper .page-inner section.normal code .css .hljs-hexcolor {
+ color: #3e999f;
+}
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-function,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-function,
+.book .book-body .page-wrapper .page-inner section.normal pre .python .hljs-decorator,
+.book .book-body .page-wrapper .page-inner section.normal code .python .hljs-decorator,
+.book .book-body .page-wrapper .page-inner section.normal pre .python .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal code .python .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-function .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-function .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-title .hljs-keyword,
+.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-title .hljs-keyword,
+.book .book-body .page-wrapper .page-inner section.normal pre .perl .hljs-sub,
+.book .book-body .page-wrapper .page-inner section.normal code .perl .hljs-sub,
+.book .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal pre .coffeescript .hljs-title,
+.book .book-body .page-wrapper .page-inner section.normal code .coffeescript .hljs-title {
+ color: #4271ae;
+}
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs-keyword,
+.book .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-function,
+.book .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-function {
+ color: #8959a8;
+}
+.book .book-body .page-wrapper .page-inner section.normal pre .hljs,
+.book .book-body .page-wrapper .page-inner section.normal code .hljs {
+ display: block;
+ background: white;
+ color: #4d4d4c;
+ padding: 0.5em;
+}
+.book .book-body .page-wrapper .page-inner section.normal pre .coffeescript .javascript,
+.book .book-body .page-wrapper .page-inner section.normal code .coffeescript .javascript,
+.book .book-body .page-wrapper .page-inner section.normal pre .javascript .xml,
+.book .book-body .page-wrapper .page-inner section.normal code .javascript .xml,
+.book .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula,
+.book .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula,
+.book .book-body .page-wrapper .page-inner section.normal pre .xml .javascript,
+.book .book-body .page-wrapper .page-inner section.normal code .xml .javascript,
+.book .book-body .page-wrapper .page-inner section.normal pre .xml .vbscript,
+.book .book-body .page-wrapper .page-inner section.normal code .xml .vbscript,
+.book .book-body .page-wrapper .page-inner section.normal pre .xml .css,
+.book .book-body .page-wrapper .page-inner section.normal code .xml .css,
+.book .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata,
+.book .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata {
+ opacity: 0.5;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code {
+ /*
+
+Orginal Style from ethanschoonover.com/solarized (c) Jeremy Hull
+
+*/
+ /* Solarized Green */
+ /* Solarized Cyan */
+ /* Solarized Blue */
+ /* Solarized Yellow */
+ /* Solarized Orange */
+ /* Solarized Red */
+ /* Solarized Violet */
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs {
+ display: block;
+ padding: 0.5em;
+ background: #fdf6e3;
+ color: #657b83;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-comment,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-template_comment,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-template_comment,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-header,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .diff .hljs-header,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-doctype,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-doctype,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-pi,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-pi,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .lisp .hljs-string,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .lisp .hljs-string,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-javadoc,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-javadoc {
+ color: #93a1a1;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-winutils,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-winutils,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .method,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .method,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-addition,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-addition,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-tag,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-tag,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-request,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-request,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-status,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-status,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .nginx .hljs-title,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .nginx .hljs-title {
+ color: #859900;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-number,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-number,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-command,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-command,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-string,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-string,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag .hljs-value,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-tag .hljs-value,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-rules .hljs-value,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-rules .hljs-value,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-phpdoc,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-phpdoc,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-hexcolor,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-hexcolor,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_url,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_url {
+ color: #2aa198;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-title,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-title,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-localvars,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-localvars,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-chunk,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-chunk,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-decorator,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-decorator,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-identifier,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-identifier,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .vhdl .hljs-literal,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .vhdl .hljs-literal,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-id,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-id,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-function,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-function {
+ color: #268bd2;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-variable,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .lisp .hljs-body,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .lisp .hljs-body,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .smalltalk .hljs-number,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .smalltalk .hljs-number,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-constant,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-constant,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-class .hljs-title,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-class .hljs-title,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-parent,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-parent,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .haskell .hljs-type,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .haskell .hljs-type,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_reference,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_reference {
+ color: #b58900;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor .hljs-keyword,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor .hljs-keyword,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-pragma,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-shebang,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-shebang,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol .hljs-string,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol .hljs-string,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-change,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .diff .hljs-change,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-special,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-special,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attr_selector,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attr_selector,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-subst,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-subst,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-cdata,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-cdata,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .clojure .hljs-title,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .clojure .hljs-title,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-header,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-header {
+ color: #cb4b16;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-deletion,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-important,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-important {
+ color: #dc322f;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link_label,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link_label {
+ color: #6c71c4;
+}
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula,
+.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula {
+ background: #eee8d5;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code {
+ /* Tomorrow Night Bright Theme */
+ /* Original theme - https://github.com/chriskempson/tomorrow-theme */
+ /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */
+ /* Tomorrow Comment */
+ /* Tomorrow Red */
+ /* Tomorrow Orange */
+ /* Tomorrow Yellow */
+ /* Tomorrow Green */
+ /* Tomorrow Aqua */
+ /* Tomorrow Blue */
+ /* Tomorrow Purple */
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-comment,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-title {
+ color: #969896;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-variable,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-tag,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-constant,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-constant,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-tag .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-tag .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-pi,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-pi,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-doctype,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-doctype,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .html .hljs-doctype,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .html .hljs-doctype,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-id,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-id,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-class,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-class,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-pseudo,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-pseudo {
+ color: #d54e53;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-number,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-number,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-preprocessor,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-preprocessor,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-pragma,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-pragma,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-literal,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-literal,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-params,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-params,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-constant,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-constant {
+ color: #e78c45;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-class .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-class .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-rules .hljs-attribute,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-rules .hljs-attribute {
+ color: #e7c547;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-string,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-string,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-value,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-value,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-inheritance,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-inheritance,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-header,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-header,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-symbol,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-symbol,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata {
+ color: #b9ca4a;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .css .hljs-hexcolor,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .css .hljs-hexcolor {
+ color: #70c0b1;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-function,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-function,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .python .hljs-decorator,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .python .hljs-decorator,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .python .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .python .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-function .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-function .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-title .hljs-keyword,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-title .hljs-keyword,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .perl .hljs-sub,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .perl .hljs-sub,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .coffeescript .hljs-title,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .coffeescript .hljs-title {
+ color: #7aa6da;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .hljs-function,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .hljs-function {
+ color: #c397d8;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs {
+ display: block;
+ background: black;
+ color: #eaeaea;
+ padding: 0.5em;
+}
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .coffeescript .javascript,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .coffeescript .javascript,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .javascript .xml,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .javascript .xml,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .tex .hljs-formula,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .tex .hljs-formula,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .javascript,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .javascript,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .vbscript,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .vbscript,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .css,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .css,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .xml .hljs-cdata,
+.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .xml .hljs-cdata {
+ opacity: 0.5;
+}
diff --git a/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-search.css b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-search.css
new file mode 100644
index 0000000..c85e557
--- /dev/null
+++ b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-search.css
@@ -0,0 +1,31 @@
+.book .book-summary .book-search {
+ padding: 6px;
+ background: transparent;
+ position: absolute;
+ top: -50px;
+ left: 0px;
+ right: 0px;
+ transition: top 0.5s ease;
+}
+.book .book-summary .book-search input,
+.book .book-summary .book-search input:focus,
+.book .book-summary .book-search input:hover {
+ width: 100%;
+ background: transparent;
+ border: 1px solid #ccc;
+ box-shadow: none;
+ outline: none;
+ line-height: 22px;
+ padding: 7px 4px;
+ color: inherit;
+ box-sizing: border-box;
+}
+.book.with-search .book-summary .book-search {
+ top: 0px;
+}
+.book.with-search .book-summary ul.summary {
+ top: 50px;
+}
+.with-search .summary li[data-level] a[href*=".html#"] {
+ display: none;
+}
diff --git a/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-table.css b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-table.css
new file mode 100644
index 0000000..7fba1b9
--- /dev/null
+++ b/english/courses/analytics2020/libs/gitbook-2.6.7/css/plugin-table.css
@@ -0,0 +1 @@
+.book .book-body .page-wrapper .page-inner section.normal table{display:table;width:100%;border-collapse:collapse;border-spacing:0;overflow:auto}.book .book-body .page-wrapper .page-inner section.normal table td,.book .book-body .page-wrapper .page-inner section.normal table th{padding:6px 13px;border:1px solid #ddd}.book .book-body .page-wrapper .page-inner section.normal table tr{background-color:#fff;border-top:1px solid #ccc}.book .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n){background-color:#f8f8f8}.book .book-body .page-wrapper .page-inner section.normal table th{font-weight:700}
diff --git a/english/courses/analytics2020/libs/gitbook-2.6.7/css/style.css b/english/courses/analytics2020/libs/gitbook-2.6.7/css/style.css
new file mode 100644
index 0000000..b896892
--- /dev/null
+++ b/english/courses/analytics2020/libs/gitbook-2.6.7/css/style.css
@@ -0,0 +1,10 @@
+/*! normalize.css v2.1.0 | MIT License | git.io/normalize */img,legend{border:0}*,.fa{-webkit-font-smoothing:antialiased}.fa-ul>li,sub,sup{position:relative}.book .book-body .page-wrapper .page-inner section.normal hr:after,.book-langs-index .inner .languages:after,.buttons:after,.dropdown-menu .buttons:after{clear:both}body,html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}.hidden,[hidden]{display:none}audio:not([controls]){display:none;height:0}html{font-family:sans-serif}body,figure{margin:0}a:focus{outline:dotted thin}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}svg:not(:root){overflow:hidden}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button{margin-right:10px;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}/*!
+ * Preboot v2
+ *
+ * Open sourced under MIT license by @mdo.
+ * Some variables and mixins from Bootstrap (Apache 2 license).
+ */.link-inherit,.link-inherit:focus,.link-inherit:hover{color:inherit}.fa,.fa-stack{display:inline-block}/*!
+ * Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:FontAwesome;src:url(./fontawesome/fontawesome-webfont.ttf?v=4.1.0) format('truetype');font-weight:400;font-style:normal}.fa{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale}.book .book-header,.book .book-summary{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0)}100%{-o-transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1,1);-moz-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-stack{position:relative;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-repeat:before,.fa-rotate-right:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-floppy-o:before,.fa-save:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-bolt:before,.fa-flash:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-chain-broken:before,.fa-unlink:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\f150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\f151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\f152"}.fa-eur:before,.fa-euro:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-inr:before,.fa-rupee:before{content:"\f156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\f158"}.fa-krw:before,.fa-won:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-try:before,.fa-turkish-lira:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\f19c"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-square:before,.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\f1c5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\f1c6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-empire:before,.fa-ge:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-paper-plane:before,.fa-send:before{content:"\f1d8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.book-langs-index{width:100%;height:100%;padding:40px 0;margin:0;overflow:auto}@media (max-width:600px){.book-langs-index{padding:0}}.book-langs-index .inner{max-width:600px;width:100%;margin:0 auto;padding:30px;background:#fff;border-radius:3px}.book-langs-index .inner h3{margin:0}.book-langs-index .inner .languages{list-style:none;padding:20px 30px;margin-top:20px;border-top:1px solid #eee}.book-langs-index .inner .languages:after,.book-langs-index .inner .languages:before{content:" ";display:table;line-height:0}.book-langs-index .inner .languages li{width:50%;float:left;padding:10px 5px;font-size:16px}@media (max-width:600px){.book-langs-index .inner .languages li{width:100%;max-width:100%}}.book .book-header{overflow:visible;height:50px;padding:0 8px;z-index:2;font-size:.85em;color:#7e888b;background:0 0}.book .book-header .btn{display:block;height:50px;padding:0 15px;border-bottom:none;color:#ccc;text-transform:uppercase;line-height:50px;-webkit-box-shadow:none!important;box-shadow:none!important;position:relative;font-size:14px}.book .book-header .btn:hover{position:relative;text-decoration:none;color:#444;background:0 0}.book .book-header h1{margin:0;font-size:20px;font-weight:200;text-align:center;line-height:50px;opacity:0;padding-left:200px;padding-right:200px;-webkit-transition:opacity .2s ease;-moz-transition:opacity .2s ease;-o-transition:opacity .2s ease;transition:opacity .2s ease;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.book .book-header h1 a,.book .book-header h1 a:hover{color:inherit;text-decoration:none}@media (max-width:1000px){.book .book-header h1{display:none}}.book .book-header h1 i{display:none}.book .book-header:hover h1{opacity:1}.book.is-loading .book-header h1 i{display:inline-block}.book.is-loading .book-header h1 a{display:none}.dropdown{position:relative}.dropdown-menu{position:absolute;top:100%;left:0;z-index:100;display:none;float:left;min-width:160px;padding:0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fafafa;border:1px solid rgba(0,0,0,.07);border-radius:1px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.open{display:block}.dropdown-menu.dropdown-left{left:auto;right:4%}.dropdown-menu.dropdown-left .dropdown-caret{right:14px;left:auto}.dropdown-menu .dropdown-caret{position:absolute;top:-8px;left:14px;width:18px;height:10px;float:left;overflow:hidden}.dropdown-menu .dropdown-caret .caret-inner,.dropdown-menu .dropdown-caret .caret-outer{display:inline-block;top:0;border-left:9px solid transparent;border-right:9px solid transparent;position:absolute}.dropdown-menu .dropdown-caret .caret-outer{border-bottom:9px solid rgba(0,0,0,.1);height:auto;left:0;width:auto;margin-left:-1px}.dropdown-menu .dropdown-caret .caret-inner{margin-top:-1px;top:1px;border-bottom:9px solid #fafafa}.dropdown-menu .buttons{border-bottom:1px solid rgba(0,0,0,.07)}.dropdown-menu .buttons:after,.dropdown-menu .buttons:before{content:" ";display:table;line-height:0}.dropdown-menu .buttons:last-child{border-bottom:none}.dropdown-menu .buttons .button{border:0;background-color:transparent;color:#a6a6a6;width:100%;text-align:center;float:left;line-height:1.42857143;padding:8px 4px}.alert,.dropdown-menu .buttons .button:hover{color:#444}.dropdown-menu .buttons .button:focus,.dropdown-menu .buttons .button:hover{outline:0}.dropdown-menu .buttons .button.size-2{width:50%}.dropdown-menu .buttons .button.size-3{width:33%}.alert{padding:15px;margin-bottom:20px;background:#eee;border-bottom:5px solid #ddd}.alert-success{background:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-info{background:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-danger{background:#f2dede;border-color:#ebccd1;color:#a94442}.alert-warning{background:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.book .book-summary{position:absolute;top:0;left:-300px;bottom:0;z-index:1;width:300px;color:#364149;background:#fafafa;border-right:1px solid rgba(0,0,0,.07);-webkit-transition:left 250ms ease;-moz-transition:left 250ms ease;-o-transition:left 250ms ease;transition:left 250ms ease}.book .book-summary ul.summary{position:absolute;top:0;left:0;right:0;bottom:0;overflow-y:auto;list-style:none;margin:0;padding:0;-webkit-transition:top .5s ease;-moz-transition:top .5s ease;-o-transition:top .5s ease;transition:top .5s ease}.book .book-summary ul.summary li{list-style:none}.book .book-summary ul.summary li.divider{height:1px;margin:7px 0;overflow:hidden;background:rgba(0,0,0,.07)}.book .book-summary ul.summary li i.fa-check{display:none;position:absolute;right:9px;top:16px;font-size:9px;color:#3c3}.book .book-summary ul.summary li.done>a{color:#364149;font-weight:400}.book .book-summary ul.summary li.done>a i{display:inline}.book .book-summary ul.summary li a,.book .book-summary ul.summary li span{display:block;padding:10px 15px;border-bottom:none;color:#364149;background:0 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;position:relative}.book .book-summary ul.summary li span{cursor:not-allowed;opacity:.3;filter:alpha(opacity=30)}.book .book-summary ul.summary li a:hover,.book .book-summary ul.summary li.active>a{color:#008cff;background:0 0;text-decoration:none}.book .book-summary ul.summary li ul{padding-left:20px}@media (max-width:600px){.book .book-summary{width:calc(100% - 60px);bottom:0;left:-100%}}.book.with-summary .book-summary{left:0}.book.without-animation .book-summary{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.book{position:relative;width:100%;height:100%}.book .book-body,.book .book-body .body-inner{position:absolute;top:0;left:0;overflow-y:auto;bottom:0;right:0}.book .book-body{color:#000;background:#fff;-webkit-transition:left 250ms ease;-moz-transition:left 250ms ease;-o-transition:left 250ms ease;transition:left 250ms ease}.book .book-body .page-wrapper{position:relative;outline:0}.book .book-body .page-wrapper .page-inner{max-width:800px;margin:0 auto;padding:20px 0 40px}.book .book-body .page-wrapper .page-inner section{margin:0;padding:5px 15px;background:#fff;border-radius:2px;line-height:1.7;font-size:1.6rem}.book .book-body .page-wrapper .page-inner .btn-group .btn{border-radius:0;background:#eee;border:0}@media (max-width:1240px){.book .book-body{-webkit-transition:-webkit-transform 250ms ease;-moz-transition:-moz-transform 250ms ease;-o-transition:-o-transform 250ms ease;transition:transform 250ms ease;padding-bottom:20px}.book .book-body .body-inner{position:static;min-height:calc(100% - 50px)}}@media (min-width:600px){.book.with-summary .book-body{left:300px}}@media (max-width:600px){.book.with-summary{overflow:hidden}.book.with-summary .book-body{-webkit-transform:translate(calc(100% - 60px),0);-moz-transform:translate(calc(100% - 60px),0);-ms-transform:translate(calc(100% - 60px),0);-o-transform:translate(calc(100% - 60px),0);transform:translate(calc(100% - 60px),0)}}.book.without-animation .book-body{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.buttons:after,.buttons:before{content:" ";display:table;line-height:0}.button{border:0;background:#eee;color:#666;width:100%;text-align:center;float:left;line-height:1.42857143;padding:8px 4px}.button:hover{color:#444}.button:focus,.button:hover{outline:0}.button.size-2{width:50%}.button.size-3{width:33%}.book .book-body .page-wrapper .page-inner section{display:none}.book .book-body .page-wrapper .page-inner section.normal{display:block;word-wrap:break-word;overflow:hidden;color:#333;line-height:1.7;text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%}.book .book-body .page-wrapper .page-inner section.normal *{box-sizing:border-box;-webkit-box-sizing:border-box;}.book .book-body .page-wrapper .page-inner section.normal>:first-child{margin-top:0!important}.book .book-body .page-wrapper .page-inner section.normal>:last-child{margin-bottom:0!important}.book .book-body .page-wrapper .page-inner section.normal blockquote,.book .book-body .page-wrapper .page-inner section.normal code,.book .book-body .page-wrapper .page-inner section.normal figure,.book .book-body .page-wrapper .page-inner section.normal img,.book .book-body .page-wrapper .page-inner section.normal pre,.book .book-body .page-wrapper .page-inner section.normal table,.book .book-body .page-wrapper .page-inner section.normal tr{page-break-inside:avoid}.book .book-body .page-wrapper .page-inner section.normal h2,.book .book-body .page-wrapper .page-inner section.normal h3,.book .book-body .page-wrapper .page-inner section.normal h4,.book .book-body .page-wrapper .page-inner section.normal h5,.book .book-body .page-wrapper .page-inner section.normal p{orphans:3;widows:3}.book .book-body .page-wrapper .page-inner section.normal h1,.book .book-body .page-wrapper .page-inner section.normal h2,.book .book-body .page-wrapper .page-inner section.normal h3,.book .book-body .page-wrapper .page-inner section.normal h4,.book .book-body .page-wrapper .page-inner section.normal h5{page-break-after:avoid}.book .book-body .page-wrapper .page-inner section.normal b,.book .book-body .page-wrapper .page-inner section.normal strong{font-weight:700}.book .book-body .page-wrapper .page-inner section.normal em{font-style:italic}.book .book-body .page-wrapper .page-inner section.normal blockquote,.book .book-body .page-wrapper .page-inner section.normal dl,.book .book-body .page-wrapper .page-inner section.normal ol,.book .book-body .page-wrapper .page-inner section.normal p,.book .book-body .page-wrapper .page-inner section.normal table,.book .book-body .page-wrapper .page-inner section.normal ul{margin-top:0;margin-bottom:.85em}.book .book-body .page-wrapper .page-inner section.normal a{color:#4183c4;text-decoration:none;background:0 0}.book .book-body .page-wrapper .page-inner section.normal a:active,.book .book-body .page-wrapper .page-inner section.normal a:focus,.book .book-body .page-wrapper .page-inner section.normal a:hover{outline:0;text-decoration:underline}.book .book-body .page-wrapper .page-inner section.normal img{border:0;max-width:100%}.book .book-body .page-wrapper .page-inner section.normal hr{height:4px;padding:0;margin:1.7em 0;overflow:hidden;background-color:#e7e7e7;border:none}.book .book-body .page-wrapper .page-inner section.normal hr:after,.book .book-body .page-wrapper .page-inner section.normal hr:before{display:table;content:" "}.book .book-body .page-wrapper .page-inner section.normal h1,.book .book-body .page-wrapper .page-inner section.normal h2,.book .book-body .page-wrapper .page-inner section.normal h3,.book .book-body .page-wrapper .page-inner section.normal h4,.book .book-body .page-wrapper .page-inner section.normal h5,.book .book-body .page-wrapper .page-inner section.normal h6{margin-top:1.275em;margin-bottom:.85em;}.book .book-body .page-wrapper .page-inner section.normal h1{font-size:2em}.book .book-body .page-wrapper .page-inner section.normal h2{font-size:1.75em}.book .book-body .page-wrapper .page-inner section.normal h3{font-size:1.5em}.book .book-body .page-wrapper .page-inner section.normal h4{font-size:1.25em}.book .book-body .page-wrapper .page-inner section.normal h5{font-size:1em}.book .book-body .page-wrapper .page-inner section.normal h6{font-size:1em;color:#777}.book .book-body .page-wrapper .page-inner section.normal code,.book .book-body .page-wrapper .page-inner section.normal pre{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;direction:ltr;border:none;color:inherit}.book .book-body .page-wrapper .page-inner section.normal pre{overflow:auto;word-wrap:normal;margin:0 0 1.275em;padding:.85em 1em;background:#f7f7f7}.book .book-body .page-wrapper .page-inner section.normal pre>code{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;font-size:.85em;white-space:pre;background:0 0}.book .book-body .page-wrapper .page-inner section.normal pre>code:after,.book .book-body .page-wrapper .page-inner section.normal pre>code:before{content:normal}.book .book-body .page-wrapper .page-inner section.normal code{padding:.2em;margin:0;font-size:.85em;background-color:#f7f7f7}.book .book-body .page-wrapper .page-inner section.normal code:after,.book .book-body .page-wrapper .page-inner section.normal code:before{letter-spacing:-.2em;content:"\00a0"}.book .book-body .page-wrapper .page-inner section.normal ol,.book .book-body .page-wrapper .page-inner section.normal ul{padding:0 0 0 2em;margin:0 0 .85em}.book .book-body .page-wrapper .page-inner section.normal ol ol,.book .book-body .page-wrapper .page-inner section.normal ol ul,.book .book-body .page-wrapper .page-inner section.normal ul ol,.book .book-body .page-wrapper .page-inner section.normal ul ul{margin-top:0;margin-bottom:0}.book .book-body .page-wrapper .page-inner section.normal ol ol{list-style-type:lower-roman}.book .book-body .page-wrapper .page-inner section.normal blockquote{margin:0 0 .85em;padding:0 15px;opacity:0.75;border-left:4px solid #dcdcdc}.book .book-body .page-wrapper .page-inner section.normal blockquote:first-child{margin-top:0}.book .book-body .page-wrapper .page-inner section.normal blockquote:last-child{margin-bottom:0}.book .book-body .page-wrapper .page-inner section.normal dl{padding:0}.book .book-body .page-wrapper .page-inner section.normal dl dt{padding:0;margin-top:.85em;font-style:italic;font-weight:700}.book .book-body .page-wrapper .page-inner section.normal dl dd{padding:0 .85em;margin-bottom:.85em}.book .book-body .page-wrapper .page-inner section.normal dd{margin-left:0}.book .book-body .page-wrapper .page-inner section.normal .glossary-term{cursor:help;text-decoration:underline}.book .book-body .navigation{position:absolute;top:50px;bottom:0;margin:0;max-width:150px;min-width:90px;display:flex;justify-content:center;align-content:center;flex-direction:column;font-size:40px;color:#ccc;text-align:center;-webkit-transition:all 350ms ease;-moz-transition:all 350ms ease;-o-transition:all 350ms ease;transition:all 350ms ease}.book .book-body .navigation:hover{text-decoration:none;color:#444}.book .book-body .navigation.navigation-next{right:0}.book .book-body .navigation.navigation-prev{left:0}@media (max-width:1240px){.book .book-body .navigation{position:static;top:auto;max-width:50%;width:50%;display:inline-block;float:left}.book .book-body .navigation.navigation-unique{max-width:100%;width:100%}}.book .book-body .page-wrapper .page-inner section.glossary{margin-bottom:40px}.book .book-body .page-wrapper .page-inner section.glossary h2 a,.book .book-body .page-wrapper .page-inner section.glossary h2 a:hover{color:inherit;text-decoration:none}.book .book-body .page-wrapper .page-inner section.glossary .glossary-index{list-style:none;margin:0;padding:0}.book .book-body .page-wrapper .page-inner section.glossary .glossary-index li{display:inline;margin:0 8px;white-space:nowrap}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-overflow-scrolling:touch;-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:none;-webkit-touch-callout:none}a{text-decoration:none}body,html{height:100%}html{font-size:62.5%}body{text-rendering:optimizeLegibility;font-smoothing:antialiased;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;letter-spacing:.2px;text-size-adjust:100%}
+.book .book-summary ul.summary li a span {display:inline;padding:initial;overflow:visible;cursor:auto;opacity:1;}
diff --git a/english/courses/analytics2020/libs/gitbook-2.6.7/js/app.min.js b/english/courses/analytics2020/libs/gitbook-2.6.7/js/app.min.js
new file mode 100644
index 0000000..643f1f9
--- /dev/null
+++ b/english/courses/analytics2020/libs/gitbook-2.6.7/js/app.min.js
@@ -0,0 +1 @@
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o"'`]/g,reHasEscapedHtml=RegExp(reEscapedHtml.source),reHasUnescapedHtml=RegExp(reUnescapedHtml.source);var reEscape=/<%-([\s\S]+?)%>/g,reEvaluate=/<%([\s\S]+?)%>/g,reInterpolate=/<%=([\s\S]+?)%>/g;var reIsDeepProp=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,reIsPlainProp=/^\w*$/,rePropName=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;var reRegExpChars=/^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,reHasRegExpChars=RegExp(reRegExpChars.source);var reComboMark=/[\u0300-\u036f\ufe20-\ufe23]/g;var reEscapeChar=/\\(\\)?/g;var reEsTemplate=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;var reFlags=/\w*$/;var reHasHexPrefix=/^0[xX]/;var reIsHostCtor=/^\[object .+?Constructor\]$/;var reIsUint=/^\d+$/;var reLatin1=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;var reNoMatch=/($^)/;var reUnescapedString=/['\n\r\u2028\u2029\\]/g;var reWords=function(){var upper="[A-Z\\xc0-\\xd6\\xd8-\\xde]",lower="[a-z\\xdf-\\xf6\\xf8-\\xff]+";return RegExp(upper+"+(?="+upper+lower+")|"+upper+"?"+lower+"|"+upper+"+|[0-9]+","g")}();var contextProps=["Array","ArrayBuffer","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Math","Number","Object","RegExp","Set","String","_","clearTimeout","isFinite","parseFloat","parseInt","setTimeout","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap"];var templateCounter=-1;var typedArrayTags={};typedArrayTags[float32Tag]=typedArrayTags[float64Tag]=typedArrayTags[int8Tag]=typedArrayTags[int16Tag]=typedArrayTags[int32Tag]=typedArrayTags[uint8Tag]=typedArrayTags[uint8ClampedTag]=typedArrayTags[uint16Tag]=typedArrayTags[uint32Tag]=true;typedArrayTags[argsTag]=typedArrayTags[arrayTag]=typedArrayTags[arrayBufferTag]=typedArrayTags[boolTag]=typedArrayTags[dateTag]=typedArrayTags[errorTag]=typedArrayTags[funcTag]=typedArrayTags[mapTag]=typedArrayTags[numberTag]=typedArrayTags[objectTag]=typedArrayTags[regexpTag]=typedArrayTags[setTag]=typedArrayTags[stringTag]=typedArrayTags[weakMapTag]=false;var cloneableTags={};cloneableTags[argsTag]=cloneableTags[arrayTag]=cloneableTags[arrayBufferTag]=cloneableTags[boolTag]=cloneableTags[dateTag]=cloneableTags[float32Tag]=cloneableTags[float64Tag]=cloneableTags[int8Tag]=cloneableTags[int16Tag]=cloneableTags[int32Tag]=cloneableTags[numberTag]=cloneableTags[objectTag]=cloneableTags[regexpTag]=cloneableTags[stringTag]=cloneableTags[uint8Tag]=cloneableTags[uint8ClampedTag]=cloneableTags[uint16Tag]=cloneableTags[uint32Tag]=true;cloneableTags[errorTag]=cloneableTags[funcTag]=cloneableTags[mapTag]=cloneableTags[setTag]=cloneableTags[weakMapTag]=false;var deburredLetters={"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss"};var htmlEscapes={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};var htmlUnescapes={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"};var objectTypes={function:true,object:true};var regexpEscapes={0:"x30",1:"x31",2:"x32",3:"x33",4:"x34",5:"x35",6:"x36",7:"x37",8:"x38",9:"x39",A:"x41",B:"x42",C:"x43",D:"x44",E:"x45",F:"x46",a:"x61",b:"x62",c:"x63",d:"x64",e:"x65",f:"x66",n:"x6e",r:"x72",t:"x74",u:"x75",v:"x76",x:"x78"};var stringEscapes={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"};var freeExports=objectTypes[typeof exports]&&exports&&!exports.nodeType&&exports;var freeModule=objectTypes[typeof module]&&module&&!module.nodeType&&module;var freeGlobal=freeExports&&freeModule&&typeof global=="object"&&global&&global.Object&&global;var freeSelf=objectTypes[typeof self]&&self&&self.Object&&self;var freeWindow=objectTypes[typeof window]&&window&&window.Object&&window;var moduleExports=freeModule&&freeModule.exports===freeExports&&freeExports;var root=freeGlobal||freeWindow!==(this&&this.window)&&freeWindow||freeSelf||this;function baseCompareAscending(value,other){if(value!==other){var valIsNull=value===null,valIsUndef=value===undefined,valIsReflexive=value===value;var othIsNull=other===null,othIsUndef=other===undefined,othIsReflexive=other===other;if(value>other&&!othIsNull||!valIsReflexive||valIsNull&&!othIsUndef&&othIsReflexive||valIsUndef&&othIsReflexive){return 1}if(value-1){}return index}function charsRightIndex(string,chars){var index=string.length;while(index--&&chars.indexOf(string.charAt(index))>-1){}return index}function compareAscending(object,other){return baseCompareAscending(object.criteria,other.criteria)||object.index-other.index}function compareMultiple(object,other,orders){var index=-1,objCriteria=object.criteria,othCriteria=other.criteria,length=objCriteria.length,ordersLength=orders.length;while(++index=ordersLength){return result}var order=orders[index];return result*(order==="asc"||order===true?1:-1)}}return object.index-other.index}function deburrLetter(letter){return deburredLetters[letter]}function escapeHtmlChar(chr){return htmlEscapes[chr]}function escapeRegExpChar(chr,leadingChar,whitespaceChar){if(leadingChar){chr=regexpEscapes[chr]}else if(whitespaceChar){chr=stringEscapes[chr]}return"\\"+chr}function escapeStringChar(chr){return"\\"+stringEscapes[chr]}function indexOfNaN(array,fromIndex,fromRight){var length=array.length,index=fromIndex+(fromRight?0:-1);while(fromRight?index--:++index=9&&charCode<=13)||charCode==32||charCode==160||charCode==5760||charCode==6158||charCode>=8192&&(charCode<=8202||charCode==8232||charCode==8233||charCode==8239||charCode==8287||charCode==12288||charCode==65279)}function replaceHolders(array,placeholder){var index=-1,length=array.length,resIndex=-1,result=[];while(++index>>1;var MAX_SAFE_INTEGER=9007199254740991;var metaMap=WeakMap&&new WeakMap;var realNames={};function lodash(value){if(isObjectLike(value)&&!isArray(value)&&!(value instanceof LazyWrapper)){if(value instanceof LodashWrapper){return value}if(hasOwnProperty.call(value,"__chain__")&&hasOwnProperty.call(value,"__wrapped__")){return wrapperClone(value)}}return new LodashWrapper(value)}function baseLodash(){}function LodashWrapper(value,chainAll,actions){this.__wrapped__=value;this.__actions__=actions||[];this.__chain__=!!chainAll}var support=lodash.support={};lodash.templateSettings={escape:reEscape,evaluate:reEvaluate,interpolate:reInterpolate,variable:"",imports:{_:lodash}};function LazyWrapper(value){this.__wrapped__=value;this.__actions__=[];this.__dir__=1;this.__filtered__=false;this.__iteratees__=[];this.__takeCount__=POSITIVE_INFINITY;this.__views__=[]}function lazyClone(){var result=new LazyWrapper(this.__wrapped__);result.__actions__=arrayCopy(this.__actions__);result.__dir__=this.__dir__;result.__filtered__=this.__filtered__;result.__iteratees__=arrayCopy(this.__iteratees__);result.__takeCount__=this.__takeCount__;result.__views__=arrayCopy(this.__views__);return result}function lazyReverse(){if(this.__filtered__){var result=new LazyWrapper(this);result.__dir__=-1;result.__filtered__=true}else{result=this.clone();result.__dir__*=-1}return result}function lazyValue(){var array=this.__wrapped__.value(),dir=this.__dir__,isArr=isArray(array),isRight=dir<0,arrLength=isArr?array.length:0,view=getView(0,arrLength,this.__views__),start=view.start,end=view.end,length=end-start,index=isRight?end:start-1,iteratees=this.__iteratees__,iterLength=iteratees.length,resIndex=0,takeCount=nativeMin(length,this.__takeCount__);if(!isArr||arrLength=LARGE_ARRAY_SIZE?createCache(values):null,valuesLength=values.length;if(cache){indexOf=cacheIndexOf;isCommon=false;values=cache}outer:while(++indexlength?0:length+start}end=end===undefined||end>length?length:+end||0;if(end<0){end+=length}length=start>end?0:end>>>0;start>>>=0;while(startlength?0:length+start}end=end===undefined||end>length?length:+end||0;if(end<0){end+=length}length=start>end?0:end-start>>>0;start>>>=0;var result=Array(length);while(++index=LARGE_ARRAY_SIZE,seen=isLarge?createCache():null,result=[];if(seen){indexOf=cacheIndexOf;isCommon=false}else{isLarge=false;seen=iteratee?[]:result}outer:while(++index>>1,computed=array[mid];if((retHighest?computed<=value:computed2?sources[length-2]:undefined,guard=length>2?sources[2]:undefined,thisArg=length>1?sources[length-1]:undefined;if(typeof customizer=="function"){customizer=bindCallback(customizer,thisArg,5);length-=2}else{customizer=typeof thisArg=="function"?thisArg:undefined;length-=customizer?1:0}if(guard&&isIterateeCall(sources[0],sources[1],guard)){customizer=length<3?undefined:customizer;length=1}while(++index-1?collection[index]:undefined}return baseFind(collection,predicate,eachFunc)}}function createFindIndex(fromRight){return function(array,predicate,thisArg){if(!(array&&array.length)){return-1}predicate=getCallback(predicate,thisArg,3);return baseFindIndex(array,predicate,fromRight)}}function createFindKey(objectFunc){return function(object,predicate,thisArg){predicate=getCallback(predicate,thisArg,3);return baseFind(object,predicate,objectFunc,true)}}function createFlow(fromRight){return function(){var wrapper,length=arguments.length,index=fromRight?length:-1,leftIndex=0,funcs=Array(length);while(fromRight?index--:++index=LARGE_ARRAY_SIZE){return wrapper.plant(value).value()}var index=0,result=length?funcs[index].apply(this,args):value;while(++index=length||!nativeIsFinite(length)){return""}var padLength=length-strLength;chars=chars==null?" ":chars+"";return repeat(chars,nativeCeil(padLength/chars.length)).slice(0,padLength)}function createPartialWrapper(func,bitmask,thisArg,partials){var isBind=bitmask&BIND_FLAG,Ctor=createCtorWrapper(func);function wrapper(){var argsIndex=-1,argsLength=arguments.length,leftIndex=-1,leftLength=partials.length,args=Array(leftLength+argsLength);while(++leftIndexarrLength)){return false}while(++index-1&&value%1==0&&value-1&&value%1==0&&value<=MAX_SAFE_INTEGER}function isStrictComparable(value){return value===value&&!isObject(value)}function mergeData(data,source){var bitmask=data[1],srcBitmask=source[1],newBitmask=bitmask|srcBitmask,isCommon=newBitmask0){if(++count>=HOT_COUNT){return key}}else{count=0}return baseSetData(key,value)}}();function shimKeys(object){var props=keysIn(object),propsLength=props.length,length=propsLength&&object.length;var allowIndexes=!!length&&isLength(length)&&(isArray(object)||isArguments(object));var index=-1,result=[];while(++index=120?createCache(othIndex&&value):null}var array=arrays[0],index=-1,length=array?array.length:0,seen=caches[0];outer:while(++index-1){splice.call(array,fromIndex,1)}}return array}var pullAt=restParam(function(array,indexes){indexes=baseFlatten(indexes);var result=baseAt(array,indexes);basePullAt(array,indexes.sort(baseCompareAscending));return result});function remove(array,predicate,thisArg){var result=[];if(!(array&&array.length)){return result}var index=-1,indexes=[],length=array.length;predicate=getCallback(predicate,thisArg,3);while(++index2?arrays[length-2]:undefined,thisArg=length>1?arrays[length-1]:undefined;if(length>2&&typeof iteratee=="function"){length-=2}else{iteratee=length>1&&typeof thisArg=="function"?(--length,thisArg):undefined;thisArg=undefined}arrays.length=length;return unzipWith(arrays,iteratee,thisArg)});function chain(value){var result=lodash(value);result.__chain__=true;return result}function tap(value,interceptor,thisArg){interceptor.call(thisArg,value);return value}function thru(value,interceptor,thisArg){return interceptor.call(thisArg,value)}function wrapperChain(){return chain(this)}function wrapperCommit(){return new LodashWrapper(this.value(),this.__chain__)}var wrapperConcat=restParam(function(values){values=baseFlatten(values);return this.thru(function(array){return arrayConcat(isArray(array)?array:[toObject(array)],values)})});function wrapperPlant(value){var result,parent=this;while(parent instanceof baseLodash){var clone=wrapperClone(parent);if(result){previous.__wrapped__=clone}else{result=clone}var previous=clone;parent=parent.__wrapped__}previous.__wrapped__=value;return result}function wrapperReverse(){var value=this.__wrapped__;var interceptor=function(value){return wrapped&&wrapped.__dir__<0?value:value.reverse()};if(value instanceof LazyWrapper){var wrapped=value;if(this.__actions__.length){wrapped=new LazyWrapper(this)}wrapped=wrapped.reverse();wrapped.__actions__.push({func:thru,args:[interceptor],thisArg:undefined});return new LodashWrapper(wrapped,this.__chain__)}return this.thru(interceptor)}function wrapperToString(){return this.value()+""}function wrapperValue(){return baseWrapperValue(this.__wrapped__,this.__actions__)}var at=restParam(function(collection,props){return baseAt(collection,baseFlatten(props))});var countBy=createAggregator(function(result,value,key){hasOwnProperty.call(result,key)?++result[key]:result[key]=1});function every(collection,predicate,thisArg){var func=isArray(collection)?arrayEvery:baseEvery;if(thisArg&&isIterateeCall(collection,predicate,thisArg)){predicate=undefined}if(typeof predicate!="function"||thisArg!==undefined){predicate=getCallback(predicate,thisArg,3)}return func(collection,predicate)}function filter(collection,predicate,thisArg){var func=isArray(collection)?arrayFilter:baseFilter;predicate=getCallback(predicate,thisArg,3);return func(collection,predicate)}var find=createFind(baseEach);var findLast=createFind(baseEachRight,true);function findWhere(collection,source){return find(collection,baseMatches(source))}var forEach=createForEach(arrayEach,baseEach);var forEachRight=createForEach(arrayEachRight,baseEachRight);var groupBy=createAggregator(function(result,value,key){if(hasOwnProperty.call(result,key)){result[key].push(value)}else{result[key]=[value]}});function includes(collection,target,fromIndex,guard){var length=collection?getLength(collection):0;if(!isLength(length)){collection=values(collection);length=collection.length}if(typeof fromIndex!="number"||guard&&isIterateeCall(target,fromIndex,guard)){fromIndex=0}else{fromIndex=fromIndex<0?nativeMax(length+fromIndex,0):fromIndex||0}return typeof collection=="string"||!isArray(collection)&&isString(collection)?fromIndex<=length&&collection.indexOf(target,fromIndex)>-1:!!length&&getIndexOf(collection,target,fromIndex)>-1}var indexBy=createAggregator(function(result,value,key){result[key]=value});var invoke=restParam(function(collection,path,args){var index=-1,isFunc=typeof path=="function",isProp=isKey(path),result=isArrayLike(collection)?Array(collection.length):[];baseEach(collection,function(value){var func=isFunc?path:isProp&&value!=null?value[path]:undefined;result[++index]=func?func.apply(value,args):invokePath(value,path,args)});return result});function map(collection,iteratee,thisArg){var func=isArray(collection)?arrayMap:baseMap;iteratee=getCallback(iteratee,thisArg,3);return func(collection,iteratee)}var partition=createAggregator(function(result,value,key){result[key?0:1].push(value)},function(){return[[],[]]});function pluck(collection,path){return map(collection,property(path))}var reduce=createReduce(arrayReduce,baseEach);var reduceRight=createReduce(arrayReduceRight,baseEachRight);function reject(collection,predicate,thisArg){var func=isArray(collection)?arrayFilter:baseFilter;predicate=getCallback(predicate,thisArg,3);return func(collection,function(value,index,collection){return!predicate(value,index,collection)})}function sample(collection,n,guard){if(guard?isIterateeCall(collection,n,guard):n==null){collection=toIterable(collection);var length=collection.length;return length>0?collection[baseRandom(0,length-1)]:undefined}var index=-1,result=toArray(collection),length=result.length,lastIndex=length-1;n=nativeMin(n<0?0:+n||0,length);while(++index0){result=func.apply(this,arguments)}if(n<=1){func=undefined}return result}}var bind=restParam(function(func,thisArg,partials){var bitmask=BIND_FLAG;if(partials.length){var holders=replaceHolders(partials,bind.placeholder);bitmask|=PARTIAL_FLAG}return createWrapper(func,bitmask,thisArg,partials,holders)});var bindAll=restParam(function(object,methodNames){methodNames=methodNames.length?baseFlatten(methodNames):functions(object);var index=-1,length=methodNames.length;while(++indexwait){complete(trailingCall,maxTimeoutId)}else{timeoutId=setTimeout(delayed,remaining)}}function maxDelayed(){complete(trailing,timeoutId)}function debounced(){args=arguments;stamp=now();thisArg=this;trailingCall=trailing&&(timeoutId||!leading);if(maxWait===false){var leadingCall=leading&&!timeoutId}else{if(!maxTimeoutId&&!leading){lastCalled=stamp}var remaining=maxWait-(stamp-lastCalled),isCalled=remaining<=0||remaining>maxWait;if(isCalled){if(maxTimeoutId){maxTimeoutId=clearTimeout(maxTimeoutId)}lastCalled=stamp;result=func.apply(thisArg,args)}else if(!maxTimeoutId){maxTimeoutId=setTimeout(maxDelayed,remaining)}}if(isCalled&&timeoutId){timeoutId=clearTimeout(timeoutId)}else if(!timeoutId&&wait!==maxWait){timeoutId=setTimeout(delayed,wait)}if(leadingCall){isCalled=true;result=func.apply(thisArg,args)}if(isCalled&&!timeoutId&&!maxTimeoutId){args=thisArg=undefined}return result}debounced.cancel=cancel;return debounced}var defer=restParam(function(func,args){return baseDelay(func,1,args)});var delay=restParam(function(func,wait,args){return baseDelay(func,wait,args)});var flow=createFlow();var flowRight=createFlow(true);function memoize(func,resolver){if(typeof func!="function"||resolver&&typeof resolver!="function"){throw new TypeError(FUNC_ERROR_TEXT)}var memoized=function(){var args=arguments,key=resolver?resolver.apply(this,args):args[0],cache=memoized.cache;if(cache.has(key)){return cache.get(key)}var result=func.apply(this,args);memoized.cache=cache.set(key,result);return result};memoized.cache=new memoize.Cache;return memoized}var modArgs=restParam(function(func,transforms){transforms=baseFlatten(transforms);if(typeof func!="function"||!arrayEvery(transforms,baseIsFunction)){throw new TypeError(FUNC_ERROR_TEXT)}var length=transforms.length;return restParam(function(args){var index=nativeMin(args.length,length);while(index--){args[index]=transforms[index](args[index])}return func.apply(this,args)})});function negate(predicate){if(typeof predicate!="function"){throw new TypeError(FUNC_ERROR_TEXT)}return function(){return!predicate.apply(this,arguments)}}function once(func){return before(2,func)}var partial=createPartial(PARTIAL_FLAG);var partialRight=createPartial(PARTIAL_RIGHT_FLAG);var rearg=restParam(function(func,indexes){return createWrapper(func,REARG_FLAG,undefined,undefined,undefined,baseFlatten(indexes))});function restParam(func,start){if(typeof func!="function"){throw new TypeError(FUNC_ERROR_TEXT)}start=nativeMax(start===undefined?func.length-1:+start||0,0);return function(){var args=arguments,index=-1,length=nativeMax(args.length-start,0),rest=Array(length);while(++indexother}function gte(value,other){return value>=other}function isArguments(value){return isObjectLike(value)&&isArrayLike(value)&&hasOwnProperty.call(value,"callee")&&!propertyIsEnumerable.call(value,"callee")}var isArray=nativeIsArray||function(value){return isObjectLike(value)&&isLength(value.length)&&objToString.call(value)==arrayTag};function isBoolean(value){return value===true||value===false||isObjectLike(value)&&objToString.call(value)==boolTag}function isDate(value){return isObjectLike(value)&&objToString.call(value)==dateTag}function isElement(value){return!!value&&value.nodeType===1&&isObjectLike(value)&&!isPlainObject(value)}function isEmpty(value){if(value==null){return true}if(isArrayLike(value)&&(isArray(value)||isString(value)||isArguments(value)||isObjectLike(value)&&isFunction(value.splice))){return!value.length}return!keys(value).length}function isEqual(value,other,customizer,thisArg){customizer=typeof customizer=="function"?bindCallback(customizer,thisArg,3):undefined;var result=customizer?customizer(value,other):undefined;return result===undefined?baseIsEqual(value,other,customizer):!!result}function isError(value){return isObjectLike(value)&&typeof value.message=="string"&&objToString.call(value)==errorTag}function isFinite(value){return typeof value=="number"&&nativeIsFinite(value)}function isFunction(value){return isObject(value)&&objToString.call(value)==funcTag}function isObject(value){var type=typeof value;return!!value&&(type=="object"||type=="function")}function isMatch(object,source,customizer,thisArg){customizer=typeof customizer=="function"?bindCallback(customizer,thisArg,3):undefined;return baseIsMatch(object,getMatchData(source),customizer)}function isNaN(value){return isNumber(value)&&value!=+value}function isNative(value){if(value==null){return false}if(isFunction(value)){return reIsNative.test(fnToString.call(value))}return isObjectLike(value)&&reIsHostCtor.test(value)}function isNull(value){return value===null}function isNumber(value){return typeof value=="number"||isObjectLike(value)&&objToString.call(value)==numberTag}function isPlainObject(value){var Ctor;if(!(isObjectLike(value)&&objToString.call(value)==objectTag&&!isArguments(value))||!hasOwnProperty.call(value,"constructor")&&(Ctor=value.constructor,typeof Ctor=="function"&&!(Ctor instanceof Ctor))){return false}var result;baseForIn(value,function(subValue,key){result=key});return result===undefined||hasOwnProperty.call(value,result)}function isRegExp(value){return isObject(value)&&objToString.call(value)==regexpTag}function isString(value){return typeof value=="string"||isObjectLike(value)&&objToString.call(value)==stringTag}function isTypedArray(value){return isObjectLike(value)&&isLength(value.length)&&!!typedArrayTags[objToString.call(value)]}function isUndefined(value){return value===undefined}function lt(value,other){return value0;while(++index=nativeMin(start,end)&&value=0&&string.indexOf(target,position)==position}function escape(string){string=baseToString(string);return string&&reHasUnescapedHtml.test(string)?string.replace(reUnescapedHtml,escapeHtmlChar):string}function escapeRegExp(string){string=baseToString(string);return string&&reHasRegExpChars.test(string)?string.replace(reRegExpChars,escapeRegExpChar):string||"(?:)"}var kebabCase=createCompounder(function(result,word,index){return result+(index?"-":"")+word.toLowerCase()});function pad(string,length,chars){string=baseToString(string);length=+length;var strLength=string.length;if(strLength>=length||!nativeIsFinite(length)){return string}var mid=(length-strLength)/2,leftLength=nativeFloor(mid),rightLength=nativeCeil(mid);chars=createPadding("",rightLength,chars);return chars.slice(0,leftLength)+string+chars}var padLeft=createPadDir();var padRight=createPadDir(true);function parseInt(string,radix,guard){if(guard?isIterateeCall(string,radix,guard):radix==null){radix=0}else if(radix){radix=+radix}string=trim(string);return nativeParseInt(string,radix||(reHasHexPrefix.test(string)?16:10))}function repeat(string,n){var result="";string=baseToString(string);n=+n;if(n<1||!string||!nativeIsFinite(n)){return result}do{if(n%2){result+=string}n=nativeFloor(n/2);string+=string}while(n);return result}var snakeCase=createCompounder(function(result,word,index){return result+(index?"_":"")+word.toLowerCase()});var startCase=createCompounder(function(result,word,index){return result+(index?" ":"")+(word.charAt(0).toUpperCase()+word.slice(1))});function startsWith(string,target,position){string=baseToString(string);position=position==null?0:nativeMin(position<0?0:+position||0,string.length);return string.lastIndexOf(target,position)==position}function template(string,options,otherOptions){var settings=lodash.templateSettings;if(otherOptions&&isIterateeCall(string,options,otherOptions)){options=otherOptions=undefined}string=baseToString(string);options=assignWith(baseAssign({},otherOptions||options),settings,assignOwnDefaults);var imports=assignWith(baseAssign({},options.imports),settings.imports,assignOwnDefaults),importsKeys=keys(imports),importsValues=baseValues(imports,importsKeys);var isEscaping,isEvaluating,index=0,interpolate=options.interpolate||reNoMatch,source="__p += '";var reDelimiters=RegExp((options.escape||reNoMatch).source+"|"+interpolate.source+"|"+(interpolate===reInterpolate?reEsTemplate:reNoMatch).source+"|"+(options.evaluate||reNoMatch).source+"|$","g");var sourceURL="//# sourceURL="+("sourceURL"in options?options.sourceURL:"lodash.templateSources["+ ++templateCounter+"]")+"\n";string.replace(reDelimiters,function(match,escapeValue,interpolateValue,esTemplateValue,evaluateValue,offset){interpolateValue||(interpolateValue=esTemplateValue);source+=string.slice(index,offset).replace(reUnescapedString,escapeStringChar);if(escapeValue){isEscaping=true;source+="' +\n__e("+escapeValue+") +\n'"}if(evaluateValue){isEvaluating=true;source+="';\n"+evaluateValue+";\n__p += '"}if(interpolateValue){source+="' +\n((__t = ("+interpolateValue+")) == null ? '' : __t) +\n'"}index=offset+match.length;return match});source+="';\n";var variable=options.variable;if(!variable){source="with (obj) {\n"+source+"\n}\n"}source=(isEvaluating?source.replace(reEmptyStringLeading,""):source).replace(reEmptyStringMiddle,"$1").replace(reEmptyStringTrailing,"$1;");source="function("+(variable||"obj")+") {\n"+(variable?"":"obj || (obj = {});\n")+"var __t, __p = ''"+(isEscaping?", __e = _.escape":"")+(isEvaluating?", __j = Array.prototype.join;\n"+"function print() { __p += __j.call(arguments, '') }\n":";\n")+source+"return __p\n}";var result=attempt(function(){return Function(importsKeys,sourceURL+"return "+source).apply(undefined,importsValues)});result.source=source;if(isError(result)){throw result}return result}function trim(string,chars,guard){var value=string;string=baseToString(string);if(!string){return string}if(guard?isIterateeCall(value,chars,guard):chars==null){return string.slice(trimmedLeftIndex(string),trimmedRightIndex(string)+1)}chars=chars+"";return string.slice(charsLeftIndex(string,chars),charsRightIndex(string,chars)+1)}function trimLeft(string,chars,guard){var value=string;string=baseToString(string);if(!string){return string}if(guard?isIterateeCall(value,chars,guard):chars==null){return string.slice(trimmedLeftIndex(string))}return string.slice(charsLeftIndex(string,chars+""))}function trimRight(string,chars,guard){var value=string;string=baseToString(string);if(!string){return string}if(guard?isIterateeCall(value,chars,guard):chars==null){return string.slice(0,trimmedRightIndex(string)+1)}return string.slice(0,charsRightIndex(string,chars+"")+1)}function trunc(string,options,guard){if(guard&&isIterateeCall(string,options,guard)){options=undefined}var length=DEFAULT_TRUNC_LENGTH,omission=DEFAULT_TRUNC_OMISSION;if(options!=null){if(isObject(options)){var separator="separator"in options?options.separator:separator;length="length"in options?+options.length||0:length;omission="omission"in options?baseToString(options.omission):omission}else{length=+options||0}}string=baseToString(string);if(length>=string.length){return string}var end=length-omission.length;if(end<1){return omission}var result=string.slice(0,end);if(separator==null){return result+omission}if(isRegExp(separator)){if(string.slice(end).search(separator)){var match,newEnd,substring=string.slice(0,end);if(!separator.global){separator=RegExp(separator.source,(reFlags.exec(separator)||"")+"g")}separator.lastIndex=0;while(match=separator.exec(substring)){newEnd=match.index}result=result.slice(0,newEnd==null?end:newEnd)}}else if(string.indexOf(separator,end)!=end){var index=result.lastIndexOf(separator);if(index>-1){result=result.slice(0,index)}}return result+omission}function unescape(string){string=baseToString(string);return string&&reHasEscapedHtml.test(string)?string.replace(reEscapedHtml,unescapeHtmlChar):string}function words(string,pattern,guard){if(guard&&isIterateeCall(string,pattern,guard)){pattern=undefined}string=baseToString(string);return string.match(pattern||reWords)||[]}var attempt=restParam(function(func,args){try{return func.apply(undefined,args)}catch(e){return isError(e)?e:new Error(e)}});function callback(func,thisArg,guard){if(guard&&isIterateeCall(func,thisArg,guard)){thisArg=undefined}return isObjectLike(func)?matches(func):baseCallback(func,thisArg)}function constant(value){return function(){return value}}function identity(value){return value}function matches(source){return baseMatches(baseClone(source,true))}function matchesProperty(path,srcValue){return baseMatchesProperty(path,baseClone(srcValue,true))}var method=restParam(function(path,args){return function(object){return invokePath(object,path,args)}});var methodOf=restParam(function(object,args){return function(path){return invokePath(object,path,args)}});function mixin(object,source,options){if(options==null){var isObj=isObject(source),props=isObj?keys(source):undefined,methodNames=props&&props.length?baseFunctions(source,props):undefined;if(!(methodNames?methodNames.length:isObj)){methodNames=false;options=source;source=object;object=this}}if(!methodNames){methodNames=baseFunctions(source,keys(source))}var chain=true,index=-1,isFunc=isFunction(object),length=methodNames.length;if(options===false){chain=false}else if(isObject(options)&&"chain"in options){chain=options.chain}while(++index0||end<0)){return new LazyWrapper(result)}if(start<0){result=result.takeRight(-start)}else if(start){result=result.drop(start)}if(end!==undefined){end=+end||0;result=end<0?result.dropRight(-end):result.take(end-start)}return result};LazyWrapper.prototype.takeRightWhile=function(predicate,thisArg){return this.reverse().takeWhile(predicate,thisArg).reverse()};LazyWrapper.prototype.toArray=function(){return this.take(POSITIVE_INFINITY)};baseForOwn(LazyWrapper.prototype,function(func,methodName){var checkIteratee=/^(?:filter|map|reject)|While$/.test(methodName),retUnwrapped=/^(?:first|last)$/.test(methodName),lodashFunc=lodash[retUnwrapped?"take"+(methodName=="last"?"Right":""):methodName];if(!lodashFunc){return}lodash.prototype[methodName]=function(){var args=retUnwrapped?[1]:arguments,chainAll=this.__chain__,value=this.__wrapped__,isHybrid=!!this.__actions__.length,isLazy=value instanceof LazyWrapper,iteratee=args[0],useLazy=isLazy||isArray(value);if(useLazy&&checkIteratee&&typeof iteratee=="function"&&iteratee.length!=1){isLazy=useLazy=false}var interceptor=function(value){return retUnwrapped&&chainAll?lodashFunc(value,1)[0]:lodashFunc.apply(undefined,arrayPush([value],args))};var action={func:thru,args:[interceptor],thisArg:undefined},onlyLazy=isLazy&&!isHybrid;if(retUnwrapped&&!chainAll){if(onlyLazy){value=value.clone();value.__actions__.push(action);return func.call(value)}return lodashFunc.call(undefined,this.value())[0]}if(!retUnwrapped&&useLazy){value=onlyLazy?value:new LazyWrapper(this);var result=func.apply(value,args);result.__actions__.push(action);return new LodashWrapper(result,chainAll)}return this.thru(interceptor)}});arrayEach(["join","pop","push","replace","shift","sort","splice","split","unshift"],function(methodName){var func=(/^(?:replace|split)$/.test(methodName)?stringProto:arrayProto)[methodName],chainName=/^(?:push|sort|unshift)$/.test(methodName)?"tap":"thru",retUnwrapped=/^(?:join|pop|replace|shift)$/.test(methodName);lodash.prototype[methodName]=function(){var args=arguments;if(retUnwrapped&&!this.__chain__){return func.apply(this.value(),args)}return this[chainName](function(value){return func.apply(value,args)})}});baseForOwn(LazyWrapper.prototype,function(func,methodName){var lodashFunc=lodash[methodName];if(lodashFunc){var key=lodashFunc.name,names=realNames[key]||(realNames[key]=[]);names.push({name:methodName,func:lodashFunc})}});realNames[createHybridWrapper(undefined,BIND_KEY_FLAG).name]=[{name:"wrapper",func:undefined}];LazyWrapper.prototype.clone=lazyClone;LazyWrapper.prototype.reverse=lazyReverse;LazyWrapper.prototype.value=lazyValue;lodash.prototype.chain=wrapperChain;lodash.prototype.commit=wrapperCommit;lodash.prototype.concat=wrapperConcat;lodash.prototype.plant=wrapperPlant;lodash.prototype.reverse=wrapperReverse;lodash.prototype.toString=wrapperToString;lodash.prototype.run=lodash.prototype.toJSON=lodash.prototype.valueOf=lodash.prototype.value=wrapperValue;lodash.prototype.collect=lodash.prototype.map;lodash.prototype.head=lodash.prototype.first;lodash.prototype.select=lodash.prototype.filter;lodash.prototype.tail=lodash.prototype.rest;return lodash}var _=runInContext();if(typeof define=="function"&&typeof define.amd=="object"&&define.amd){root._=_;define(function(){return _})}else if(freeExports&&freeModule){if(moduleExports){(freeModule.exports=_)._=_}else{freeExports._=_}}else{root._=_}}).call(this)}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}],3:[function(require,module,exports){(function(window,document,undefined){var _MAP={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"};var _KEYCODE_MAP={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"};var _SHIFT_MAP={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"};var _SPECIAL_ALIASES={option:"alt",command:"meta",return:"enter",escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"};var _REVERSE_MAP;for(var i=1;i<20;++i){_MAP[111+i]="f"+i}for(i=0;i<=9;++i){_MAP[i+96]=i}function _addEvent(object,type,callback){if(object.addEventListener){object.addEventListener(type,callback,false);return}object.attachEvent("on"+type,callback)}function _characterFromEvent(e){if(e.type=="keypress"){var character=String.fromCharCode(e.which);if(!e.shiftKey){character=character.toLowerCase()}return character}if(_MAP[e.which]){return _MAP[e.which]}if(_KEYCODE_MAP[e.which]){return _KEYCODE_MAP[e.which]}return String.fromCharCode(e.which).toLowerCase()}function _modifiersMatch(modifiers1,modifiers2){return modifiers1.sort().join(",")===modifiers2.sort().join(",")}function _eventModifiers(e){var modifiers=[];if(e.shiftKey){modifiers.push("shift")}if(e.altKey){modifiers.push("alt")}if(e.ctrlKey){modifiers.push("ctrl")}if(e.metaKey){modifiers.push("meta")}return modifiers}function _preventDefault(e){if(e.preventDefault){e.preventDefault();return}e.returnValue=false}function _stopPropagation(e){if(e.stopPropagation){e.stopPropagation();return}e.cancelBubble=true}function _isModifier(key){return key=="shift"||key=="ctrl"||key=="alt"||key=="meta"}function _getReverseMap(){if(!_REVERSE_MAP){_REVERSE_MAP={};for(var key in _MAP){if(key>95&&key<112){continue}if(_MAP.hasOwnProperty(key)){_REVERSE_MAP[_MAP[key]]=key}}}return _REVERSE_MAP}function _pickBestAction(key,modifiers,action){if(!action){action=_getReverseMap()[key]?"keydown":"keypress"}if(action=="keypress"&&modifiers.length){action="keydown"}return action}function _keysFromString(combination){if(combination==="+"){return["+"]}combination=combination.replace(/\+{2}/g,"+plus");return combination.split("+")}function _getKeyInfo(combination,action){var keys;var key;var i;var modifiers=[];keys=_keysFromString(combination);for(i=0;i1){_bindSequence(combination,sequence,callback,action);return}info=_getKeyInfo(combination,action);self._callbacks[info.key]=self._callbacks[info.key]||[];_getMatches(info.key,info.modifiers,{type:info.action},sequenceName,combination,level);self._callbacks[info.key][sequenceName?"unshift":"push"]({callback:callback,modifiers:info.modifiers,action:info.action,seq:sequenceName,level:level,combo:combination})}self._bindMultiple=function(combinations,callback,action){for(var i=0;i-1){return false}if(_belongsTo(element,self.target)){return false}return element.tagName=="INPUT"||element.tagName=="SELECT"||element.tagName=="TEXTAREA"||element.isContentEditable};Mousetrap.prototype.handleKey=function(){var self=this;return self._handleKey.apply(self,arguments)};Mousetrap.init=function(){var documentMousetrap=Mousetrap(document);for(var method in documentMousetrap){if(method.charAt(0)!=="_"){Mousetrap[method]=function(method){return function(){return documentMousetrap[method].apply(documentMousetrap,arguments)}}(method)}}};Mousetrap.init();window.Mousetrap=Mousetrap;if(typeof module!=="undefined"&&module.exports){module.exports=Mousetrap}if(typeof define==="function"&&define.amd){define(function(){return Mousetrap})}})(window,document)},{}],4:[function(require,module,exports){(function(process){function normalizeArray(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up--;up){parts.unshift("..")}}return parts}var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;var splitPath=function(filename){return splitPathRe.exec(filename).slice(1)};exports.resolve=function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:process.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){continue}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=normalizeArray(filter(resolvedPath.split("/"),function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."};exports.normalize=function(path){var isAbsolute=exports.isAbsolute(path),trailingSlash=substr(path,-1)==="/";path=normalizeArray(filter(path.split("/"),function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path};exports.isAbsolute=function(path){return path.charAt(0)==="/"};exports.join=function(){var paths=Array.prototype.slice.call(arguments,0);return exports.normalize(filter(paths,function(p,index){if(typeof p!=="string"){throw new TypeError("Arguments to path.join must be strings")}return p}).join("/"))};exports.relative=function(from,to){from=exports.resolve(from).substr(1);to=exports.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i1){for(var i=1;i= 0x80 (not a basic code point)","invalid-input":"Invalid input"},baseMinusTMin=base-tMin,floor=Math.floor,stringFromCharCode=String.fromCharCode,key;function error(type){throw RangeError(errors[type])}function map(array,fn){var length=array.length;var result=[];while(length--){result[length]=fn(array[length])}return result}function mapDomain(string,fn){var parts=string.split("@");var result="";if(parts.length>1){result=parts[0]+"@";string=parts[1]}string=string.replace(regexSeparators,".");var labels=string.split(".");var encoded=map(labels,fn).join(".");return result+encoded}function ucs2decode(string){var output=[],counter=0,length=string.length,value,extra;while(counter=55296&&value<=56319&&counter65535){value-=65536;output+=stringFromCharCode(value>>>10&1023|55296);value=56320|value&1023}output+=stringFromCharCode(value);return output}).join("")}function basicToDigit(codePoint){if(codePoint-48<10){return codePoint-22}if(codePoint-65<26){return codePoint-65}if(codePoint-97<26){return codePoint-97}return base}function digitToBasic(digit,flag){return digit+22+75*(digit<26)-((flag!=0)<<5)}function adapt(delta,numPoints,firstTime){var k=0;delta=firstTime?floor(delta/damp):delta>>1;delta+=floor(delta/numPoints);for(;delta>baseMinusTMin*tMax>>1;k+=base){delta=floor(delta/baseMinusTMin)}return floor(k+(baseMinusTMin+1)*delta/(delta+skew))}function decode(input){var output=[],inputLength=input.length,out,i=0,n=initialN,bias=initialBias,basic,j,index,oldi,w,k,digit,t,baseMinusT;basic=input.lastIndexOf(delimiter);if(basic<0){basic=0}for(j=0;j=128){error("not-basic")}output.push(input.charCodeAt(j))}for(index=basic>0?basic+1:0;index=inputLength){error("invalid-input")}digit=basicToDigit(input.charCodeAt(index++));if(digit>=base||digit>floor((maxInt-i)/w)){error("overflow")}i+=digit*w;t=k<=bias?tMin:k>=bias+tMax?tMax:k-bias;if(digitfloor(maxInt/baseMinusT)){error("overflow")}w*=baseMinusT}out=output.length+1;bias=adapt(i-oldi,out,oldi==0);if(floor(i/out)>maxInt-n){error("overflow")}n+=floor(i/out);i%=out;output.splice(i++,0,n)}return ucs2encode(output)}function encode(input){var n,delta,handledCPCount,basicLength,bias,j,m,q,k,t,currentValue,output=[],inputLength,handledCPCountPlusOne,baseMinusT,qMinusT;input=ucs2decode(input);inputLength=input.length;n=initialN;delta=0;bias=initialBias;for(j=0;j=n&¤tValuefloor((maxInt-delta)/handledCPCountPlusOne)){error("overflow")}delta+=(m-n)*handledCPCountPlusOne;n=m;for(j=0;jmaxInt){error("overflow")}if(currentValue==n){for(q=delta,k=base;;k+=base){t=k<=bias?tMin:k>=bias+tMax?tMax:k-bias;if(q0&&len>maxKeys){len=maxKeys}for(var i=0;i=0){kstr=x.substr(0,idx);vstr=x.substr(idx+1)}else{kstr=x;vstr=""}k=decodeURIComponent(kstr);v=decodeURIComponent(vstr);if(!hasOwnProperty(obj,k)){obj[k]=v}else if(isArray(obj[k])){obj[k].push(v)}else{obj[k]=[obj[k],v]}}return obj};var isArray=Array.isArray||function(xs){return Object.prototype.toString.call(xs)==="[object Array]"}},{}],8:[function(require,module,exports){"use strict";var stringifyPrimitive=function(v){switch(typeof v){case"string":return v;case"boolean":return v?"true":"false";case"number":return isFinite(v)?v:"";default:return""}};module.exports=function(obj,sep,eq,name){sep=sep||"&";eq=eq||"=";if(obj===null){obj=undefined}if(typeof obj==="object"){return map(objectKeys(obj),function(k){var ks=encodeURIComponent(stringifyPrimitive(k))+eq;if(isArray(obj[k])){return map(obj[k],function(v){return ks+encodeURIComponent(stringifyPrimitive(v))}).join(sep)}else{return ks+encodeURIComponent(stringifyPrimitive(obj[k]))}}).join(sep)}if(!name)return"";return encodeURIComponent(stringifyPrimitive(name))+eq+encodeURIComponent(stringifyPrimitive(obj))};var isArray=Array.isArray||function(xs){return Object.prototype.toString.call(xs)==="[object Array]"};function map(xs,f){if(xs.map)return xs.map(f);var res=[];for(var i=0;i",'"',"`"," ","\r","\n","\t"],unwise=["{","}","|","\\","^","`"].concat(delims),autoEscape=["'"].concat(unwise),nonHostChars=["%","/","?",";","#"].concat(autoEscape),hostEndingChars=["/","?","#"],hostnameMaxLen=255,hostnamePartPattern=/^[a-z0-9A-Z_-]{0,63}$/,hostnamePartStart=/^([a-z0-9A-Z_-]{0,63})(.*)$/,unsafeProtocol={javascript:true,"javascript:":true},hostlessProtocol={javascript:true,"javascript:":true},slashedProtocol={http:true,https:true,ftp:true,gopher:true,file:true,"http:":true,"https:":true,"ftp:":true,"gopher:":true,"file:":true},querystring=require("querystring");function urlParse(url,parseQueryString,slashesDenoteHost){if(url&&isObject(url)&&url instanceof Url)return url;var u=new Url;u.parse(url,parseQueryString,slashesDenoteHost);return u}Url.prototype.parse=function(url,parseQueryString,slashesDenoteHost){if(!isString(url)){throw new TypeError("Parameter 'url' must be a string, not "+typeof url)}var rest=url;rest=rest.trim();var proto=protocolPattern.exec(rest);if(proto){proto=proto[0];var lowerProto=proto.toLowerCase();this.protocol=lowerProto;rest=rest.substr(proto.length)}if(slashesDenoteHost||proto||rest.match(/^\/\/[^@\/]+@[^@\/]+/)){var slashes=rest.substr(0,2)==="//";if(slashes&&!(proto&&hostlessProtocol[proto])){rest=rest.substr(2);this.slashes=true}}if(!hostlessProtocol[proto]&&(slashes||proto&&!slashedProtocol[proto])){var hostEnd=-1;for(var i=0;i127){newpart+="x"}else{newpart+=part[j]}}if(!newpart.match(hostnamePartPattern)){var validParts=hostparts.slice(0,i);var notHost=hostparts.slice(i+1);var bit=part.match(hostnamePartStart);if(bit){validParts.push(bit[1]);notHost.unshift(bit[2])}if(notHost.length){rest="/"+notHost.join(".")+rest}this.hostname=validParts.join(".");break}}}}if(this.hostname.length>hostnameMaxLen){this.hostname=""}else{this.hostname=this.hostname.toLowerCase()}if(!ipv6Hostname){var domainArray=this.hostname.split(".");var newOut=[];for(var i=0;i0?result.host.split("@"):false;if(authInHost){result.auth=authInHost.shift();result.host=result.hostname=authInHost.shift()}}result.search=relative.search;result.query=relative.query;if(!isNull(result.pathname)||!isNull(result.search)){result.path=(result.pathname?result.pathname:"")+(result.search?result.search:"")}result.href=result.format();return result}if(!srcPath.length){result.pathname=null;if(result.search){result.path="/"+result.search}else{result.path=null}result.href=result.format();return result}var last=srcPath.slice(-1)[0];var hasTrailingSlash=(result.host||relative.host)&&(last==="."||last==="..")||last==="";var up=0;for(var i=srcPath.length;i>=0;i--){last=srcPath[i];if(last=="."){srcPath.splice(i,1)}else if(last===".."){srcPath.splice(i,1);up++}else if(up){srcPath.splice(i,1);up--}}if(!mustEndAbs&&!removeAllDots){for(;up--;up){srcPath.unshift("..")}}if(mustEndAbs&&srcPath[0]!==""&&(!srcPath[0]||srcPath[0].charAt(0)!=="/")){srcPath.unshift("")}if(hasTrailingSlash&&srcPath.join("/").substr(-1)!=="/"){srcPath.push("")}var isAbsolute=srcPath[0]===""||srcPath[0]&&srcPath[0].charAt(0)==="/";if(psychotic){result.hostname=result.host=isAbsolute?"":srcPath.length?srcPath.shift():"";var authInHost=result.host&&result.host.indexOf("@")>0?result.host.split("@"):false;if(authInHost){result.auth=authInHost.shift();result.host=result.hostname=authInHost.shift()}}mustEndAbs=mustEndAbs||result.host&&srcPath.length;if(mustEndAbs&&!isAbsolute){srcPath.unshift("")}if(!srcPath.length){result.pathname=null;result.path=null}else{result.pathname=srcPath.join("/")}if(!isNull(result.pathname)||!isNull(result.search)){result.path=(result.pathname?result.pathname:"")+(result.search?result.search:"")}result.auth=relative.auth||result.auth;result.slashes=result.slashes||relative.slashes;result.href=result.format();return result};Url.prototype.parseHost=function(){var host=this.host;var port=portPattern.exec(host);if(port){port=port[0];if(port!==":"){this.port=port.substr(1)}host=host.substr(0,host.length-port.length)}if(host)this.hostname=host};function isString(arg){return typeof arg==="string"}function isObject(arg){return typeof arg==="object"&&arg!==null}function isNull(arg){return arg===null}function isNullOrUndefined(arg){return arg==null}},{punycode:6,querystring:9}],11:[function(require,module,exports){var $=require("jquery");function toggleDropdown(e){var $dropdown=$(e.currentTarget).parent().find(".dropdown-menu");$dropdown.toggleClass("open");e.stopPropagation();e.preventDefault()}function closeDropdown(e){$(".dropdown-menu").removeClass("open")}function init(){$(document).on("click",".toggle-dropdown",toggleDropdown);$(document).on("click",".dropdown-menu",function(e){e.stopPropagation()});$(document).on("click",closeDropdown)}module.exports={init:init}},{jquery:1}],12:[function(require,module,exports){var $=require("jquery");module.exports=$({})},{jquery:1}],13:[function(require,module,exports){var $=require("jquery");var _=require("lodash");var storage=require("./storage");var dropdown=require("./dropdown");var events=require("./events");var state=require("./state");var keyboard=require("./keyboard");var navigation=require("./navigation");var sidebar=require("./sidebar");var toolbar=require("./toolbar");function start(config){sidebar.init();keyboard.init();dropdown.init();navigation.init();toolbar.createButton({index:0,icon:"fa fa-align-justify",label:"Toggle Sidebar",onClick:function(e){e.preventDefault();sidebar.toggle()}});events.trigger("start",config);navigation.notify()}var gitbook={start:start,events:events,state:state,toolbar:toolbar,sidebar:sidebar,storage:storage,keyboard:keyboard};var MODULES={gitbook:gitbook,jquery:$,lodash:_};window.gitbook=gitbook;window.$=$;window.jQuery=$;gitbook.require=function(mods,fn){mods=_.map(mods,function(mod){mod=mod.toLowerCase();if(!MODULES[mod]){throw new Error("GitBook module "+mod+" doesn't exist")}return MODULES[mod]});fn.apply(null,mods)};module.exports={}},{"./dropdown":11,"./events":12,"./keyboard":14,"./navigation":16,"./sidebar":18,"./state":19,"./storage":20,"./toolbar":21,jquery:1,lodash:2}],14:[function(require,module,exports){var Mousetrap=require("mousetrap");var navigation=require("./navigation");var sidebar=require("./sidebar");function bindShortcut(keys,fn){Mousetrap.bind(keys,function(e){fn();return false})}function init(){bindShortcut(["right"],function(e){navigation.goNext()});bindShortcut(["left"],function(e){navigation.goPrev()});bindShortcut(["s"],function(e){sidebar.toggle()})}module.exports={init:init,bind:bindShortcut}},{"./navigation":16,"./sidebar":18,mousetrap:3}],15:[function(require,module,exports){var state=require("./state");function showLoading(p){state.$book.addClass("is-loading");p.always(function(){state.$book.removeClass("is-loading")});return p}module.exports={show:showLoading}},{"./state":19}],16:[function(require,module,exports){var $=require("jquery");var url=require("url");var events=require("./events");var state=require("./state");var loading=require("./loading");var usePushState=typeof history.pushState!=="undefined";function handleNavigation(relativeUrl,push){var uri=url.resolve(window.location.pathname,relativeUrl);notifyPageChange();location.href=relativeUrl;return}function updateNavigationPosition(){var bodyInnerWidth,pageWrapperWidth;bodyInnerWidth=parseInt($(".body-inner").css("width"),10);pageWrapperWidth=parseInt($(".page-wrapper").css("width"),10);$(".navigation-next").css("margin-right",bodyInnerWidth-pageWrapperWidth+"px")}function notifyPageChange(){events.trigger("page.change")}function preparePage(notify){var $bookBody=$(".book-body");var $bookInner=$bookBody.find(".body-inner");var $pageWrapper=$bookInner.find(".page-wrapper");updateNavigationPosition();$bookInner.scrollTop(0);$bookBody.scrollTop(0);if(notify!==false)notifyPageChange()}function isLeftClickEvent(e){return e.button===0}function isModifiedEvent(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function handlePagination(e){if(isModifiedEvent(e)||!isLeftClickEvent(e)){return}e.stopPropagation();e.preventDefault();var url=$(this).attr("href");if(url)handleNavigation(url,true)}function goNext(){var url=$(".navigation-next").attr("href");if(url)handleNavigation(url,true)}function goPrev(){var url=$(".navigation-prev").attr("href");if(url)handleNavigation(url,true)}function init(){$.ajaxSetup({});if(location.protocol!=="file:"){history.replaceState({path:window.location.href},"")}window.onpopstate=function(event){if(event.state===null){return}return handleNavigation(event.state.path,false)};$(document).on("click",".navigation-prev",handlePagination);$(document).on("click",".navigation-next",handlePagination);$(document).on("click",".summary [data-path] a",handlePagination);$(window).resize(updateNavigationPosition);preparePage(false)}module.exports={init:init,goNext:goNext,goPrev:goPrev,notify:notifyPageChange}},{"./events":12,"./loading":15,"./state":19,jquery:1,url:10}],17:[function(require,module,exports){module.exports={isMobile:function(){return document.body.clientWidth<=600}}},{}],18:[function(require,module,exports){var $=require("jquery");var _=require("lodash");var storage=require("./storage");var platform=require("./platform");var state=require("./state");function toggleSidebar(_state,animation){if(state!=null&&isOpen()==_state)return;if(animation==null)animation=true;state.$book.toggleClass("without-animation",!animation);state.$book.toggleClass("with-summary",_state);storage.set("sidebar",isOpen())}function isOpen(){return state.$book.hasClass("with-summary")}function init(){if(platform.isMobile()){toggleSidebar(false,false)}else{toggleSidebar(storage.get("sidebar",true),false)}$(document).on("click",".book-summary li.chapter a",function(e){if(platform.isMobile())toggleSidebar(false,false)})}function filterSummary(paths){var $summary=$(".book-summary");$summary.find("li").each(function(){var path=$(this).data("path");var st=paths==null||_.contains(paths,path);$(this).toggle(st);if(st)$(this).parents("li").show()})}module.exports={init:init,isOpen:isOpen,toggle:toggleSidebar,filter:filterSummary}},{"./platform":17,"./state":19,"./storage":20,jquery:1,lodash:2}],19:[function(require,module,exports){var $=require("jquery");var url=require("url");var path=require("path");var state={};state.update=function(dom){var $book=$(dom.find(".book"));state.$book=$book;state.level=$book.data("level");state.basePath=$book.data("basepath");state.innerLanguage=$book.data("innerlanguage");state.revision=$book.data("revision");state.filepath=$book.data("filepath");state.chapterTitle=$book.data("chapter-title");state.root=url.resolve(location.protocol+"//"+location.host,path.dirname(path.resolve(location.pathname.replace(/\/$/,"/index.html"),state.basePath))).replace(/\/?$/,"/");state.bookRoot=state.innerLanguage?url.resolve(state.root,".."):state.root};state.update($);module.exports=state},{jquery:1,path:4,url:10}],20:[function(require,module,exports){var baseKey="";module.exports={setBaseKey:function(key){baseKey=key},set:function(key,value){key=baseKey+":"+key;try{sessionStorage[key]=JSON.stringify(value)}catch(e){}},get:function(key,def){key=baseKey+":"+key;if(sessionStorage[key]===undefined)return def;try{var v=JSON.parse(sessionStorage[key]);return v==null?def:v}catch(err){return sessionStorage[key]||def}},remove:function(key){key=baseKey+":"+key;sessionStorage.removeItem(key)}}},{}],21:[function(require,module,exports){var $=require("jquery");var _=require("lodash");var events=require("./events");var buttons=[];function insertAt(parent,selector,index,element){var lastIndex=parent.children(selector).length;if(index<0){index=Math.max(0,lastIndex+1+index)}parent.append(element);if(index",{class:"dropdown-menu",html:'
'});if(_.isString(dropdown)){$menu.append(dropdown)}else{var groups=_.map(dropdown,function(group){if(_.isArray(group))return group;else return[group]});_.each(groups,function(group){var $group=$("