Skip to content

Instantly share code, notes, and snippets.

@ql-owo-lp
Created April 25, 2012 15:56
Show Gist options
  • Save ql-owo-lp/2490858 to your computer and use it in GitHub Desktop.
Save ql-owo-lp/2490858 to your computer and use it in GitHub Desktop.
Former G++ Script (Reply function and so on)
// ==UserScript==
// @name G++
// @id google_plus_plus_pokerface
// @namespace me.senseofti.toolkit.google
// @description Google Plus Forger. Make your own Google Plus.
// @license GPL v3 or later version
// @updateURL http://userscripts.org/scripts/source/127787.meta.js
// @exclude *://plus.google.com/_/apps-static/*
// @exclude *://plus.google.com/u/0/_/notifications/frame?*
// @include *://plus.google.com/*
// @version 0.1
// @author Pokerface - Kevin
// ==/UserScript==
/*
Google Plus Plus
Kevin Wang (kevixw'At'gmail.com)
Copyright (c) 2012 . All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
KissogramToolkit
build 4/18/2012 by Kevin
*/
var $K = KissogramToolkit = (function ($$d) {
// Basic function ==============================================
// for each
function each($arr, $func) {
if (!$arr)
return;
//console.debug('each function is called. arr length is '+ $arr.length);
if ($func)
for (var i=$arr.length-1; i >=0; i--)
$func.call($arr[i]);
else
// the $arr is collection of function itself
for (var i=$arr.length-1; (i >=0 && typeof $arr[i]=='function') ; i--)
$arr[i]();
}
var utils = {
"isStrictArray" : function ($obj) {
return Object.prototype.toString.apply($obj) === '[object Array]';
},
"isArray" : function ($obj) {
var type = Object.prototype.toString.apply($obj);
return type === '[object Array]' // array
|| type === '[object NodeList]' // document.querySelectorAll
|| type === '[object Arguments]' // function arguments
;
},
"getMinIndex" : function ($arr, $exception) {
var min = 0, maxNum = Math.max.apply(Math, $arr);
if ($exception instanceof Array)
$exception = $exception.join(',');
$exception = ","+$exception+",";
for (var i=0;i<$arr.length;i++)
if ($arr[i] <= maxNum && $exception.indexOf(','+i+',') < 0) {
min = i;
maxNum = $arr[i];
}
return min;
}
};
// shallow copy
function extend($target, $options) {
for (name in $options)
$target[name] = $options[name];
return $target;
}
// Basic function ends =============================================
// limit the interval/delay of running a specific function, return the changed function
function setFunctionTiming($func, $opt) {
$opt = $opt || {};
var opt = {
interval : $opt.interval || 0,
delay : $opt.delay || 0,
check : $opt.check || 0
};
var _delayedFunc = opt.delay > 0 ?
function () {
var _this = this, args = Array.prototype.slice.apply(arguments);
setTimeout(function () {
$func.apply(_this, args);
}, opt.delay);
}
: $func;
//if ($opt.check > 0)
// setInterval(_delayedFunc, check);
return opt.interval<=0 ? _delayedFunc : (function () {
var lastRunTime = 0, isRunning = false;
return function () {
var check = (new Date().getTime()) - lastRunTime;
var _this = this, args = Array.prototype.slice.apply(arguments);
// the real function
function runFunc() {
_delayedFunc.apply(_this, args);
lastRunTime = new Date().getTime();
isRunning = false;
};
if (!isRunning) {
isRunning = true;
// not time yet
if (check < opt.interval)
setTimeout(runFunc, opt.interval - check);
else
runFunc();
}
};
})();
}
var $$browser = (function getNavigator($n) {
var navigatorString = $n.userAgent.toLowerCase(),
// browser agent
rBrowsers = [
/.*version\/([\w.]+).*(safari).*/,
/.*(msie) ([\w.]+).*/,
/.*(firefox)\/([\w.]+).*/,
/(opera).+version\/([\w.]+)/,
/.*(chrome)\/([\w.]+).*/
],
// result
ret = {
name : 'unknown',
version : 'unknown',
language: $n.language || $n.userLanguage || '',
toString : function () {
return this.name;
}
};
for (var i = 0, match=null; i < rBrowsers.length; ++i)
if ( match = rBrowsers[i].exec(navigatorString) ) {
// match safari
ret.name = (i==0 ? match[2] : match[1]) || 'unknown';
ret.version = (i==0 ? match[1] : match[2]) || 'unknown';
ret[ret.name] = true;
break;
}
return ret;
})(navigator);
// get unsafeWindow
var $$w = (function () {
var w = null, // window object
resizeTasks = []; // current window size
function getSize() {
return {
windowHeight : window.innerHeight,
windowWidth : window.innerWidth,
height : $$d.documentElement.clientHeight,
width : $$d.documentElement.clientWidth
};
}
function _isScroll(el) {
// test targets
var elems = el ? [el] : [document.documentElement, document.body];
var scrollX = false, scrollY = false;
for (var i = 0; i < elems.length; i++) {
var o = elems[i];
// test horizontal
var sl = o.scrollLeft;
o.scrollLeft += (sl > 0) ? -1 : 1;
o.scrollLeft !== sl && (scrollX = scrollX || true);
o.scrollLeft = sl;
// test vertical
var st = o.scrollTop;
o.scrollTop += (st > 0) ? -1 : 1;
o.scrollTop !== st && (scrollY = scrollY || true);
o.scrollTop = st;
}
// ret
return {
scrollX: scrollX,
scrollY: scrollY
};
};
window.addEventListener('resize', function () {
each(resizeTasks);
}, false);
// return true when unsafeWindow is loaded successfully
function init($var) {
if (!w) {
// load unsafeWindow
if (typeof(unsafeWindow) !== "undefined" && typeof(unsafeWindow[$var]) !== "undefined")
w = unsafeWindow;
else if (typeof(window[$var]) !== "undefined")
w = window;
else
try {
// for Chrome
var a = document.createElement("a");
a.setAttribute("onclick", "return window;");
var win = a.onclick();
if (typeof(win[$var]) !== "undefined")
w = win;
}
catch (e) {
console.error('Kissogram Toolkit : Unable to load unsafeWindow Object!');
w = null;
}
}
return w;
}
var $c = {
// get unsafeWindow if possible
get : function ($var) {
return (this.getUnsafeWindow($var) || window)[$var]; // return safe window
},
// get unsafeWindow
getUnsafeWindow : function ($var) {
return init($var);
},
/*
when specific function is ready
options : {
test : a function that test if specific variable is loaded properly
retry : retry times before test() returns a failure, default is 40
interval : the interval between every check, default is 300 ms
}
*/
onReady : function ($var, $func, $options) {
$options = $options || {};
$options.retry = $options.retry || 40;
$options.interval = $options.interval || 300;
var _this=this;
if (init($var) && (($options.test && $options.test(w)) || !$options.test))
return $func(w);
if (--$options.retry > -1)
setTimeout(function () { _this.onReady($var, $func, $options); }, $options.interval);
},
size : getSize,
onResize : function ($func, $init) {
if ($init)
$func();
resizeTasks.push($func);
},
isScroll : _isScroll
};
return $c;
})();
// css Class
var $$css = (function () {
var css_enabled = [],
root = $$d.documentElement;
var instance = function ($arg) {
extend(this, $c);
if ($arg)
this.dictionary = this.dictionary.concat($arg); //define the css dictionary
};
// effective only for Chrome
function _getMediaQueriesWidth() {
if ($$browser == "firefox")
return window.innerWidth;
// for Chrome, the width in Media Queries is quite close to window.outerWidth
for (var i=1, width = window.outerWidth, match=false; !match; i++) {
if (width > 0)
match = window.matchMedia('(min-width :' + width + 'px) and (max-width:'+ width + 'px)').matches;
if (match)
return width;
width += (i%2 == 0 ? 1 : -1) * i;
}
}
var $c = {
dictionary : [],
// append a class to an element
append : function ($elem, $className) {
if (!$elem)
return;
$className = this.get($className);
var re = new RegExp(" "+$className+" ");
if (!re.test(" "+$elem.className+" "))
$elem.className += ' '+ $className;
},
remove : function ($elem, $className) {
if (!$elem)
return;
$className = this.get($className);
var re = new RegExp(" "+$className+" ");
$elem.className = (" "+$elem.className+" ").replace(re, '').replace(/^\s+|\s+$/g,'');
},
// append css
set : function ($str) {
GM_addStyle(this.get($str));
},
get : function ($str) {
for (var i=0; i<this.dictionary.length; i++)
$str = $str.replace(this.dictionary[i][0], this.dictionary[i][1]);
return $str;
},
push : function ($cssName, $str, $opt) {
$opt = $opt || {};
var attr = 'enable-css-'+ $cssName,
condition = "html["+ attr +($opt.value ? '="'+$opt.value+'"' : '')+"]";
$opt = $opt || {};
if ($opt.enable)
this.enable($cssName, $opt.value);
$str = $str.replace(/((?:[^,{]+,?)*)\s*{([^}]+)}/g, condition+" $1 {$2}");
$str = $str.replace(/,/g, ","+condition+" ");
this.set($str);
},
pull : function ($cssName) {
return css_enabled[$cssName] || null;
},
enable : function ($cssName, $value) {
$value = $value || 'yes';
root.setAttribute('enable-css-'+ $cssName, $value);
css_enabled[$cssName] = $value;
},
disable : function ($cssName) {
root.removeAttribute('enable-css-'+ $cssName);
delete css_enabled[$cssName];
},
// enable CSS when specific condition is meet
triger : function ($when, $str) {
},
select : function ($str) {
return $$d.querySelector(this.get($str));
},
selectAll : function ($str) {
return Array.prototype.slice.apply($$d.querySelectorAll(this.get($str)));
},
getMediaQueriesWidth : _getMediaQueriesWidth,
extendDictionary : function ($dic) {
this.dictionary = this.dictionary.concat($dic);
}
};
return extend(instance, $c);
})();
// manipulate cookies
var cookies = (function () {
return {};
})();
// the Class that process url change
var $$url = (function () {
var _url = formatUrl(),
urlChangeTasks = [],
hashChangeTasks = [];
function isUrlChanged($url) {
var url = formatUrl($url);
if (url != _url) {
_url = url;
return true;
}
else
return false;
}
// turn http://xxx.xxx into http://xxx.xxx/
function formatUrl($url) {
var url = $url || $$d.location.href;
if (/^https?:\/\/[\w.]+\w+$/.test(url))
url += '/';
return url;
}
function execTask($isHashChange) {
console.debug('Kissogram Toolkit: URL Changed!');
if ($isHashChange)
each(hashChangeTasks);
else
each(urlChangeTasks);
}
// mointor
var urlMonitor = setInterval(function () {
if (isUrlChanged())
execTask();
}, 500);
// bind onpopstate
window.addEventListener('popstate', function () {
if (isUrlChanged())
execTask();
}, false);
// hashchange
window.addEventListener('hashchange', function () {
execTask(true);
}, false);
var $c = {
onUrlChange : function ($func, $init) {
if ($init)
$func();
urlChangeTasks.push($func);
},
onHashChange : function ($func, $init) {
if ($init)
$func();
hashChangeTasks.push($func);
},
toString : function () {
return _url;
}
};
return $c;
})();
/*
listen to specific event
$options {
init : boolean / function
runOnce : boolean
interval
}
*/
var listen = (function () {
var interval_count=[]; // collection of interval count
return function ($selector, $event, $func, $options) {
$options = $options || {};
// $event & $init cannot be false at the same time
if (!$event && !$options.init)
return;
var evt_listener = (function ($s, $e, $f, $o) {
var id = interval_count.length,
funcWithTiming = setFunctionTiming($f, {
interval : $o.interval || 0,
delay : $o.delay || 0
});
// bind event to dom object
var _bind = function ($d, $evt) {
$d.addEventListener($evt,
(function () {
var runOnceFunc = setFunctionTiming(function () {
$f.apply($d, Array.prototype.slice.apply(arguments), false);
$d.removeEventListener($evt, runOnceFunc);
}, { delay: $o.delay }),
newFunc = function () {
funcWithTiming.apply($d, Array.prototype.slice.apply(arguments));
};
return $o.runOnce ? runOnceFunc : newFunc ;
})()
);
};
return function () {
// if $s is a element itself
var dom = (typeof $s == 'string') ? $$css.selectAll($s) : $s;
if (!utils.isArray(dom)) dom = [dom];
if (dom.length > 0) {
// dom is captured
clearInterval(interval_count[id]);
delete interval_count[id];
for (var i=0; i<dom.length; i++) {
// if the function need initiation (when the listen function capture the dom objects the first time)
if ($o.init) {
if (typeof $o.init == "function")
$o.init.call(dom[i]);
else
$f.call(dom[i]);
}
if ($e instanceof Array)
each($e, function () { _bind(dom[i], this); });
else if ($e) // when $e != null
_bind(dom[i], $e);
else // do nothing
;
}
}
}
})($selector, $event, $func, $options);
// check it later
interval_count.push(setInterval(evt_listener, 500));
}
})();
// simluate a click event
function click($elem, $options) {
if (!$elem)
return;
$options = $options || {};
var opt = {
button : $options.button || 0
};
// dispatch click event following the W3C order
var e = $$d.createEvent("MouseEvents");
e.initMouseEvent("mousedown", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, opt.button, null);
$elem.dispatchEvent(e);
e = $$d.createEvent("MouseEvents");
e.initMouseEvent("mouseup", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, opt.button, null);
$elem.dispatchEvent(e);
e = $$d.createEvent("MouseEvents");
e.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, opt.button, null);
$elem.dispatchEvent(e);
}
// Main function begin ========================================
// constructor
var $$c = function () {
};
return extend($$c, {
"each" : each,
"extend" : extend,
"css" : $$css,
"listen" : listen,
"url" : $$url,
"click" : click,
"browser" : $$browser,
"window" : $$w,
"cookies" : cookies,
"select" : $$css.select,
"selectAll" : $$css.selectAll,
"tickTork" : setFunctionTiming,
"utils" : utils
});
})(document);
var GooglePlusPlus = (function ($$d) {
console.debug('Google Plus Plus is now loaded!');
var CSS_DICTIONARY = [
[/<mainContent>/g, '.RazREb.ZI35oe'],
[/<streamContainer>/g, '.lzqA1d'],
[/<post>/g, '.lzqA1d .Wbhcze.Te'],
[/<selectedPost>/g, '.lzqA1d .Wbhcze.Te.bh'],
[/<leftSideNavigation>/g, '.ZXy9Tc.VR8ITe'],
[/<chatBox>/g, '.AOaixb.yRwDId.eub5Ne'], // maxmized chatbox
[/<pinColAttr>/g, 'pinter-col'],
[/<contentPane>/g, '#contentPane'],
[/<streamMoreButton>/g, '.E4V1D.fFgAkc'],
[/<streamMoreButtonContainer>/g,'.CfrSGe.WY2Dce.gH'],
[/<postInnerVideo>/g,'.Bz2yq .CEhkv.yPrMVe > iframe'],
[/<postInnerImageThumbnail>/g, '.yqrXXd.cPNrJ'],
[/<postHotonGooglePlusBanner>/g, '.SM0yVc.Ts'],
[/<postMainContent>/g, '.CPLjOe'],
[/<postInnerImageContainer>/g, '.jrj52d'],
[/<videoThumbnail>/g, '.CEhkv.yPrMVe > .t0Scwf.r4gluf'],
[/<singlePostProfileBlock>/g, '.kM5Oeb-OKUawf.hsHREd'],
[/<trendingBox>/g, '.L9ru2b.c-wa-Da'],
[/<shareBox>/g, '.v1WCLe']
];
var HIDE_CHATBOX = "hide-chatbox", HIDE_LEFT_SIDE_NAVIGATION = "hide-left-side-navigation", DISPLAY_CIRCLE_INFO = 'display-circle-info';
var css = new $K.css(CSS_DICTIONARY);
// hide the left side menu
css.push(HIDE_LEFT_SIDE_NAVIGATION,
'<leftSideNavigation> { \
left: -90px; \
transition: left .8s ease; \
-moz-transition: left .8s ease; \
-webkit-transition: left .8s ease; \
}', { enable : true }
);
css.push(HIDE_LEFT_SIDE_NAVIGATION, '<leftSideNavigation>:hover { left: 0px; }', { enable : true });
css.push(HIDE_LEFT_SIDE_NAVIGATION, '.EziK2e, .atQfbd { margin-left:0px !important; }', { enable : true });
// hide the chatbox
css.push(HIDE_CHATBOX,
'<chatBox> { \
transition: right .8s ease; \
-moz-transition: right .8s ease; \
-webkit-transition: right .8s ease; \
right : -160px; \
z-index: 980; \
}',
{ enable : true }
);
css.push(HIDE_CHATBOX, '<chatBox>:hover { right: 0px; }', { enable : true });
css.push(HIDE_CHATBOX, '.EziK2e.ZeMNWc, .uWF1Ke.atQfbd.GjYYId { margin-right:65px; }', { enable : true });
// new style that enable auto hiding the left side menu
css.set(
// place the navigation buttons on the black bar
'@media (min-width: 1450px) {'+
'body[black-navigation-exist] .k-YB-nb.k-YB-nb-Zg ~ #content nav[role="navigation"] {'+
'position:fixed;'+
'top: -14px;'+
'left: 750px;'+
'z-index: 990;'+
'background-color: transparent;'+
'}'+
'body[black-navigation-exist] .k-YB-nb.k-YB-nb-Zg ~ #content nav[role="navigation"] .fn.c-wa-Da.nhsZYd {'+
'color: white;'+ // Profile name
'}'+
'.NeLhq.fsfr2c {'+
'background-color: transparent;'+
'height: 0;'+
'border-bottom : 0px;'+
'}'+
'.z-ea-n[role="listbox"], .urrzYd.c-o[role="menu"] { z-index: 995 }'+ // setting menu
'}'
);
// basic css for pinterest style
css.set(
// put the user photo into post
'<post> .Ns { margin-left:50px; margin-top:10px; }'+
'<post> .Vl.EHlA9 { margin-top:20px; }'+
'<post> .MrKoMd { background: transparent; }'+
'<post> .Ye > a.k-Qf-C-RySO6d.oP{ display:inline; float:left; margin-left:80px; margin-top:10px; }'+
// photo end
'<streamContainer> { padding:20px; }'+
'<contentPane> { height:100% } '+ // main content
'<selectedPost> { z-index: 1 }'+ // top the locked post
'.vix0xf.VZAKvf { z-index:1; }'+ // make the comment panel cover the pictures
'.r4gluf, .VepHtd { background-color: white !important }' + // white backgroud for photos
'.SG.rnILlb[guidedhelpid="streamcontent"] { margin-top:75px }'+ // low the stream on profile page
'.SG[guidedhelpid="streamcontent"] { margin-left:-120px }'+
'.HX2qEd { min-height: 95px }'+ // live where - profile page
'.vmfs3b { border-bottom: 1px solid #ccc; }'+ // the line under the buttons
'.x7iMqd.VG.xGUyuf { margin-left : 10% }'+ // "someone hasn't share anything with you"
'.kM5Oeb-RxwvHe.YleYsd.o8dQjb { margin-left:-250px; margin-top:-100px}'+ // 'block someone' button on profile page
'.kM5Oeb-OKUawf.hsHREd { margin-top: -40px }'+ // photo on profile page
'{mainContent} .vcard, .oJ8yxb.kSwsJc, .jbhX0d.YQqIy { margin-top: 90px }' // profile page
);
// deal with the trending box
css.set('<trendingBox> { display:none }');
css.push(DISPLAY_CIRCLE_INFO,
'{mainContent} .vcard <trendingBox> {'+ // 'xxx' have you in circle
'display:block !important; margin-top:10px; z-index:10; background-color:white; border:1px solid #ccc;'+
'}'
);
var isNewPostArrived = (function () {
var firstPostId = null;
return function () {
var firstPost = css.select('<post>:first-child');
if (!firstPost)
return false;
var curFirstPostId = firstPost.getAttribute('id');
if (firstPostId != curFirstPostId)
return !!(firstPostId = curFirstPostId);
else
return false;
};
})();
/*
the main function calculating all the elements' top value.
$selector : CSS selector of selecting all child elements
$contentWidth : current content width,
$options : {
initTop, initLeft : fisrt element's top / left
paddingH, paddingV : the horizontal / vertical padding between bricks, default is 10px
}
*/
var GPinterest = (function () {
var COLUMN_ATTR = css.get('<pinColAttr>'), // attribute name set to each post
paddingV = paddingH = 10, // the padding between each block
leftNavigationWidth = 100, // left navigation's width is 100px
hiddenNavigationWidth = 10, // the width after hiding
hiddenChatBoxWidth = 50, // the pixels on the sceen when the chat box is hidden
mainContentLeftMargin = 80, // the margin-left of main content
chatBoxWidth = 211, // chat box's width is 211px
chatBoxGreyBoard = 20, // grey board (half)
chatBoxBorderLine = 1, // the border line of grey board
postBlockWidth = 496, // default bricks' width
perferColumn = 3, // at least how many columns should be put into the container
shortestPostHeight = 199,
deletedPostHeight = 38,
reCalculateLayoutEachXPixels = 5,
SELECTED_POST_TOP_ATTR = 'target-postition-top',
currentColumn = 0,
maxContainerWidth = getMaxContainerWidth($K.window.size().width),
brickParameters = [], posts = [];
css.set(
'<mainContent>:not(.Z77zM), .oJ8yxb.kSwsJc { margin-left : '+ mainContentLeftMargin +'px; }' // center the main stream, except on the page 'photo from your phone'
);
// hide the post not ready yet
css.set(
'<post>:not([<pinColAttr>]) { left: -999px; }'
);
// post animation
css.set(
'<post> { \
position: absolute; \
transition: all 1.2s ease; \
-moz-transition: all 1.2s ease; \
-webkit-transition: all 1.2s ease; \
} \
<post>:first-of-type { \
transition: left 1.2s ease; \
-moz-transition: left 1.2s ease; \
-webkit-transition: left 1.2s ease; \
}'
);
// animation for selected post
css.set(
'<selectedPost> { \
transition:border linear .2s,box-shadow linear .5s; \
-moz-transition:border linear .2s,-moz-box-shadow linear .5s; \
-webkit-transition:border linear .2s,-webkit-box-shadow linear .5s; \
outline:none; \
border-color:rgba(0,140,0, 0.75); \
box-shadow:0 0 30px rgba(0,140,0, 0.95); \
-moz-box-shadow:0 0 30px rgba(0,140,0, 0.95); \
-webkit-box-shadow:0 0 30px rgba(0,140,0,0.95); \
}'
);
function loadBrickCSS($windowWidth) {
var mediaQueriesEnable = false; // enable media queries can accelerate the rending
// more flexible when the media queries is off
if ($K.browser == "chrome")
mediaQueriesEnable = true;
var index = Math.floor((mediaQueriesEnable ? $K.css.getMediaQueriesWidth() : window.innerWidth) / reCalculateLayoutEachXPixels),
BRICK_PARA_ATTR = 'google-plus-pinterest-brick-para-index';
if (!mediaQueriesEnable)
css.enable(BRICK_PARA_ATTR, index);
if (brickParameters[index])
return brickParameters[index];
var para = brickParameters[index] = getBrickParameters(getMaxContainerWidth($windowWidth)), css_string ='';
// for Chrome
if (mediaQueriesEnable) {
css_string += '@media (min-width:'+
(index * reCalculateLayoutEachXPixels) +
'px) and (max-width:'+
((index+1) * reCalculateLayoutEachXPixels -1) +'px) {';
console.debug('Current window width is '+ $windowWidth +'. Apply css Media Queries : '+ css_string);
}
// set brick width
css_string +='<post>,'+
'<postInnerVideo>, <postMainContent>, <postInnerImageContainer> {' +
'width:' + para.brickWidth +'px' +
'}'+
'<postHotonGooglePlusBanner> {'+
'width:' + (para.brickWidth-2) +'px' +
'}' +
'<postInnerImageThumbnail> {'+
'max-width:' + para.brickWidth +'px' +
'}';
// offest
css_string +='<singlePostProfileBlock> {'+
'margin-left:'+ (para.brickWidth - postBlockWidth)+'px'+
'}';
//if (para.brickWidth > postBlockWidth) {
var _offsetLeft = Math.floor((para.brickWidth - postBlockWidth)/2);
// for video thumbnails
css_string += '<post> <videoThumbnail> { margin-left: '+ _offsetLeft +'px; }';
//}
for (var i=0; i< para.brickColumn; i++)
css_string += '<post>[<pinColAttr>="'+i+'"] { left: '+ i * (paddingH + para.brickWidth) +'px; }';
if (mediaQueriesEnable) {
css_string += '}'; // end of Media Queries
css.set(css_string);
}
else
css.push(BRICK_PARA_ATTR, css_string, { enable : true, value : index });
return para;
}
// get current max container width
function getMaxContainerWidth($windowWidth) {
var _chatBoxWidth = css.pull(HIDE_CHATBOX) ? hiddenChatBoxWidth : chatBoxWidth;
if (!css.select('<chatBox>'))
_chatBoxWidth = 0;
return $windowWidth - hiddenNavigationWidth - _chatBoxWidth - chatBoxGreyBoard - chatBoxBorderLine - mainContentLeftMargin;
}
// re-calculate parameters based on container width
function getBrickParameters($containerWidth) {
var containerWidth = $containerWidth + paddingH,
column = localStorage['GPinterest_peferColumn'] || 0;
if (!column) {
column = Math.round(containerWidth / (postBlockWidth + paddingH));
// at least three columns should be ensured to display
column = column > perferColumn ? column : perferColumn;
}
var postBrickWidth = Math.floor($containerWidth / column - paddingH);
return {
"brickColumn" : column,
"brickWidth" : postBrickWidth
};
}
// drag and drop =======
css.set('.Ns { cursor: url(//ssl.gstatic.com/s2/oz/images/sge/openhand_8_8.cur),move; }');
function dragAndMoveHandler_over(e, $opt) {
var elem = e.target;
console.debug($opt);
$opt.post.style.top = $opt.top;
$opt.post.style.left = $opt.left;
if (e.preventDefault)
e.preventDefault(); // Necessary. Allows us to drop.
e.dataTransfer.dropEffect = 'move'; // See the section on the DataTransfer object.
return false;
}
function dragAndMoveHandler_listener(e) {
var elem = e.target, post;
if (elem.tagName == "HEADER")
elem = elem.parentElement;
if (elem.className == "Ns")
post = elem.parentElement.parentElement.parentElement;
if (!(post && /Wbhcze Te/.test(post.className)))
return;
if (!elem.hasAttribute('draggable')) {
elem.setAttribute('draggable', 'true');
elem.addEventListener('dragover', (function () {
//var x
var leftOffset = getComputedStyle(post).getPropertyValue("left");
var topOffset = getComputedStyle(post).getPropertyValue("top");
return function (e) {
dragAndMoveHandler_over(e, { "post" : post, "left": leftOffset, "top" : topOffset });
};
})(), false);
}
}
// drag and drop ===========
// re-layout the bricks
function replaceBricks($brickPara) {
var bricks = css.selectAll('<post>'),
brickAmount = bricks.length,
ignoreColumn = ($brickPara.brickColumn != currentColumn),
tops = [], needUpdate = [];
currentColumn = $brickPara.brickColumn;
for (var i=0; i<currentColumn; i++) {
tops.push(0); // default top
needUpdate.push(ignoreColumn); // if current column need to be updated
}
for (var i=0, curCol; i<brickAmount;i++) {
// deliver post balancely
curCol = (Math.max(brickAmount-1, 0)+i) % currentColumn; // current brick's column
//curCol = $K.utils.getMinIndex(tops, exceptionColumns);
var postId = bricks[i].getAttribute("id"),
postHeight = bricks[i].offsetHeight,
needReloadPost = !bricks[i].hasAttribute(COLUMN_ATTR);
if (postHeight < deletedPostHeight) // post not ready yet
continue;
if (!posts[postId] || bricks[i].style.top=="") { // init
needUpdate[curCol] = true;
posts[postId] = {
id : postId,
column : curCol,
height : postHeight,
toString : function () {
return this.id;
},
locked : false,
selected : false
};
}
else if (!ignoreColumn && !needReloadPost)
curCol = posts[postId].column;
else
posts[postId].column = curCol;
if (posts[postId].height != postHeight) {
needUpdate[curCol] = true;
posts[postId].height = postHeight;
}
// do not move the selected / locked post
if (/ bh/.test(bricks[i].className)) {
posts[postId].selected = true;
if ((bricks[i].style.top.replace('px','') || 0) != tops[curCol]) {
if (!bricks[i].hasAttribute(SELECTED_POST_TOP_ATTR))
bricks[i].addEventListener('dblclick', function () {
if (this.hasAttribute(SELECTED_POST_TOP_ATTR)) {
this.style.top = this.getAttribute(SELECTED_POST_TOP_ATTR) +'px';
this.removeAttribute(SELECTED_POST_TOP_ATTR);
this.className = this.className.replace(/ bh/,'');
}
}, false);
bricks[i].setAttribute(SELECTED_POST_TOP_ATTR, tops[curCol]);
}
}
else if (!posts[postId].locked) {
if (ignoreColumn || needReloadPost)
bricks[i].setAttribute(COLUMN_ATTR, curCol); // update column information
if (needUpdate[curCol] || posts[postId].selected)
bricks[i].style.top = tops[curCol]+'px';
posts[postId].selected = false;
}
if (!posts[postId].locked)
tops[curCol] += postHeight + paddingV;
}
return Math.max.apply(Math, tops); // return total height
}
function appendBricks($brickPara) {
}
var layout = (function () {
var maxHeight = 0;
return function () {
//console.debug('G++ Pinterest: Re-layout at '+ new Date().getTime());
var brickPara = loadBrickCSS(window.innerWidth);
var height = replaceBricks(brickPara);
// 'more' button
if (maxHeight != height) {
maxHeight = height;
css.select('<streamMoreButtonContainer>').style.marginTop = height+'px';
}
};
})();
var timingLayout = $K.tickTork(layout, { interval : 2000, delay: 800 });
function _init() {
$K.url.onUrlChange(
function () {
$K.listen(css.get('<streamContainer>'), 'DOMSubtreeModified', timingLayout, { init: true });
}, true
);
$K.listen(css.get('<streamContainer>'), 'mousedown', dragAndMoveHandler_listener);
$K.window.onResize(timingLayout);
}
return {
"layout" : timingLayout,
"init" : _init
}
})();
// cancel a bunch of action
$K.url.onUrlChange(function () {
if (css.select('#gbx3')) {
$K.listen('#gbx3', 'mouseover', function () {
css.enable(DISPLAY_CIRCLE_INFO);
});
css.enable('black-navigation-exist');
}
else
css.disable('black-navigation-exist');
}, true );
$K.listen('#content', 'click', function () {
css.disable(DISPLAY_CIRCLE_INFO);
});
//var shareBox = css.select('<shareBox>');
//if (shareBox)
// shareBox.style.marginLeft = (window.innerWidth - 500) / 2 +'px'; // the width of share box is 500px
var Theme = GPinterest;
//$K.listen(css.get('<streamContainer>'),'click',function (){
// $K.click(css.select('<streamMoreButton>'));
//});
// a-sync
setTimeout(Theme.init, 10);
})(document);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment