<commit_before>/*===============================================================================
************   Smart Select   ************
===============================================================================*/
app.initSmartSelects = function (pageContainer) {
    var page = $(pageContainer);
    if (page.length === 0) return;

    var selects = page.find('.smart-select');
    if (selects.length === 0) return;

    selects.each(function () {
        var smartSelect = $(this);

        var $select = smartSelect.find('select');
        if ($select.length === 0) return;

        var select = $select[0];
        if (select.length === 0) return;

        var valueText = [];
        for (var i = 0; i < select.length; i++) {
            if (select[i].selected) valueText.push(select[i].textContent.trim());
        }

        var itemAfter = smartSelect.find('.item-after');
        if (itemAfter.length === 0) {
            smartSelect.find('.item-inner').append('
' + valueText.join(', ') + '
');
        }
        else {
            itemAfter.text(valueText);
        }

    });

};
app.smartSelectOpen = function (smartSelect) {
    smartSelect = $(smartSelect);
    if (smartSelect.length === 0) return;

    // Find related view
    var view = smartSelect.parents('.' + app.params.viewClass);
    if (view.length === 0) return;
    view = view[0].f7View;
    if (!view) return;

    // Collect all values
    var select = smartSelect.find('select')[0];
    var $select = $(select);
    if (select.disabled || smartSelect.hasClass('disabled') || $select.hasClass('disabled')) {
        return;
    }
    var values = {};
    values.length = select.length;
    var option;
    for (var i = 0; i < select.length; i++) {
        option = $(select[i]);
        values[i] = {
            value: select[i].value,
            text: select[i].textContent.trim(),
            selected: select[i].selected,
            group: option.parent('optgroup')[0],
            image: option.attr('data-option-image') || $select.attr('data-option-image'),
            icon: option.attr('data-option-icon') || $select.attr('data-option-icon'),
            disabled: select[i].disabled
        };
    }
    var openIn = smartSelect.attr('data-open-in');
    if (!openIn) openIn = app.params.smartSelectInPopup ? 'popup' : 'page';

    var pageTitle = smartSelect.attr('data-page-title') || smartSelect.find('.item-title').text();
    var backText = smartSelect.attr('data-back-text') || app.params.smartSelectBackText;
    var closeText = smartSelect.attr('data-popup-close-text') || smartSelect.attr('data-back-text') || app.params.smartSelectPopupCloseText ;
    var backOnSelect = smartSelect.attr('data-back-onselect') ? (smartSelect.attr('data-back-onselect') === 'true' ? true : false) : app.params.smartSelectBackOnSelect;
    var formTheme = smartSelect.attr('data-form-theme') || app.params.smartSelectFormTheme;
    var navbarTheme = smartSelect.attr('data-navbar-theme') || app.params.smartSelectNavbarTheme;

    // Generate dynamic page layout
    var id = (new Date()).getTime();
    var inputType = select.multiple ? 'checkbox' : 'radio';
    var inputName = inputType + '-' + id;
    var inputsHTML = '';
    var previousGroup;
    for (var j = 0; j < values.length; j++) {
        if (values[j].disabled) continue;
        var checked = values[j].selected ? 'checked' : '';
        if (values[j].group) {
            if (values[j].group !== previousGroup) {
                inputsHTML += '
' + values[j].group.label + '
';
                previousGroup = values[j].group;
            }
        }
        var media = '';
        if (inputType === 'checkbox') media += '';
        if (values[j].icon) media += '';
        if (values[j].image) media += '';
        inputsHTML +=
            '
' +
                '' +
                    '<input type="' + inputType + '" name="' + inputName + '" value="' + values[j].value + '" ' + checked + '>' +
                    (media !== '' ? '
' + media + '
' : '') +
                    '
' +
                        '
' + values[j].text + '
' +
                    '
' +
                '' +
            '
';
    }
    // Navbar HTML
    var navbarLeftTemplate = openIn === 'popup' ? app.params.smartSelectPopupCloseTemplate.replace(/{{closeText}}/g, closeText) : app.params.smartSelectBackTemplate.replace(/{{backText}}/g, backText);
    var navbarHTML =
        '
' +
        '
' +
            navbarLeftTemplate +
        '
' + pageTitle + '
' +
        '
' +
        '
';

    if (app.params.smartSelectNavbarTemplate) {
        if (!app._compiledTemplates.smartSelectNavbar) {
            app._compiledTemplates.smartSelectNavbar = t7.compile(app.params.smartSelectNavbarTemplate);
        }
        navbarHTML = app._compiledTemplates.smartSelectNavbar({
            pageTitle: pageTitle,
            backText: backText,
            openIn: openIn,
            inPopup: openIn === 'popup',
            inPage: openIn === 'page',
            id: id,
            inputType: inputType
        });
    }
    // Determine navbar layout type - static/fixed/through
    var noNavbar = '', noToolbar = '', navbarLayout;
    if (openIn === 'page') {
        navbarLayout = 'static';
        if (smartSelect.parents('.navbar-through').length > 0) navbarLayout = 'through';
        if (smartSelect.parents('.navbar-fixed').length > 0) navbarLayout = 'fixed';
        noToolbar = smartSelect.parents('.page').hasClass('no-toolbar') ? 'no-toolbar' : '';
        noNavbar  = smartSelect.parents('.page').hasClass('no-navbar')  ? 'no-navbar'  : 'navbar-' + navbarLayout;
    }
    else {
        navbarLayout = 'fixed';
    }

    // Page Layout
    var pageName = 'smart-select-' + inputName;

    var useSearchbar = typeof smartSelect.data('searchbar') === 'undefined' ? app.params.smartSelectSearchbar : (smartSelect.data('searchbar') === 'true' ? true : false);
    var searchbarPlaceholder, searchbarCancel;

    if (useSearchbar) {
        searchbarPlaceholder = smartSelect.data('searchbar-placeholder') || 'Search';
        searchbarCancel = smartSelect.data('searchbar-cancel') || 'Cancel';
    }

    var searchbarHTML =   '<form class="searchbar" data-search-list=".smart-select-list-' + id + '" data-search-in=".item-title">' +
                            '
' +
                                '<input type="search" placeholder="' + searchbarPlaceholder + '">' +
                                '' +
                            '
' +
                            '' + searchbarCancel + '' +
                          '</form>' +
                          '

';

    var pageHTML =
        (navbarLayout === 'through' ? navbarHTML : '') +
        '
' +
        '
' +
             (navbarLayout === 'fixed' ? navbarHTML : '') +
             (useSearchbar ? searchbarHTML : '') +
        '
' +
               (navbarLayout === 'static' ? navbarHTML : '') +
        '
' +
        '
' +
                    inputsHTML +
        '
' +
        '
' +
        '
' +
        '
' +
        '
';

    // Define popup
    var popup;

    // Event Listeners on new page
    function handleInputs(container) {
        $(container).find('input[name="' + inputName + '"]').on('change', function () {
            var input = this;
            var value = input.value;
            var optionText = [];
            if (input.type === 'checkbox') {
                var values = [];
                for (var i = 0; i < select.options.length; i++) {
                    var option = select.options[i];
                    if (option.value === value) {
                        option.selected = input.checked;
                    }
                    if (option.selected) {
                        optionText.push(option.textContent.trim());
                    }
                }
            }
            else {
                optionText = [smartSelect.find('option[value="' + value + '"]').text()];
                select.value = value;
            }

            $select.trigger('change');
            smartSelect.find('.item-after').text(optionText.join(', '));
            if (backOnSelect && inputType === 'radio') {
                if (openIn === 'popup') app.closeModal(popup);
                else view.router.back();
            }
        });
    }
    function pageInit(e) {
        var page = e.detail.page;
        if (page.name === pageName) {
            $(document).off('pageInit', pageInit);
            handleInputs(page.container);
        }
    }
    $(document).on('pageInit', pageInit);

    // Load content
    if (openIn === 'popup') {
        popup = app.popup(
                '
' +
                    '
' +
                        pageHTML +
                    '
' +
                '
'
                );
        app.initPage($(popup).find('.page'));
        handleInputs(popup);
    }
    else view.router.load({content: pageHTML});
};
<commit_msg>Integration with virtual list<commit_after>/*===============================================================================
************   Smart Select   ************
===============================================================================*/
app.initSmartSelects = function (pageContainer) {
    var page = $(pageContainer);
    if (page.length === 0) return;

    var selects = page.find('.smart-select');
    if (selects.length === 0) return;

    selects.each(function () {
        var smartSelect = $(this);

        var $select = smartSelect.find('select');
        if ($select.length === 0) return;

        var select = $select[0];
        if (select.length === 0) return;

        var valueText = [];
        for (var i = 0; i < select.length; i++) {
            if (select[i].selected) valueText.push(select[i].textContent.trim());
        }

        var itemAfter = smartSelect.find('.item-after');
        if (itemAfter.length === 0) {
            smartSelect.find('.item-inner').append('
' + valueText.join(', ') + '
');
        }
        else {
            itemAfter.text(valueText);
        }

    });

};
app.smartSelectOpen = function (smartSelect) {
    smartSelect = $(smartSelect);
    if (smartSelect.length === 0) return;

    // Find related view
    var view = smartSelect.parents('.' + app.params.viewClass);
    if (view.length === 0) return;
    view = view[0].f7View;
    if (!view) return;

    // Parameters
    var openIn = smartSelect.attr('data-open-in');
    if (!openIn) openIn = app.params.smartSelectInPopup ? 'popup' : 'page';

    var pageTitle = smartSelect.attr('data-page-title') || smartSelect.find('.item-title').text();
    var backText = smartSelect.attr('data-back-text') || app.params.smartSelectBackText;
    var closeText = smartSelect.attr('data-popup-close-text') || smartSelect.attr('data-back-text') || app.params.smartSelectPopupCloseText ;
    var backOnSelect = smartSelect.attr('data-back-onselect') ? (smartSelect.attr('data-back-onselect') === 'true' ? true : false) : app.params.smartSelectBackOnSelect;
    var formTheme = smartSelect.attr('data-form-theme') || app.params.smartSelectFormTheme;
    var navbarTheme = smartSelect.attr('data-navbar-theme') || app.params.smartSelectNavbarTheme;
    var virtualList = smartSelect.attr('data-virtual-list') === 'true';
    var virtualListItemHeight = smartSelect.attr('data-virtual-list-height');

    // Collect all options/values
    var select = smartSelect.find('select')[0];
    var $select = $(select);
    if (select.disabled || smartSelect.hasClass('disabled') || $select.hasClass('disabled')) {
        return;
    }
    var values = [];
    var id = (new Date()).getTime();
    var inputType = select.multiple ? 'checkbox' : 'radio';
    var inputName = inputType + '-' + id;
    var option, optionHasMedia, optionImage, optionIcon, optionGroup, optionGroupLabel, optionPreviousGroup, optionShowGroupLabel, previousGroup;
    for (var i = 0; i < select.length; i++) {
        option = $(select[i]);
        if (option[0].disabled) continue;
        optionImage = option.attr('data-option-image') || $select.attr('data-option-image');
        optionIcon = option.attr('data-option-icon') || $select.attr('data-option-icon');
        optionHasMedia = optionImage || optionIcon || inputType === 'checkbox';
        optionGroup = option.parent('optgroup')[0];
        optionGroupLabel = optionGroup && optionGroup.label;
        optionShowGroupLabel = false;
        if (optionGroup) {
            if (optionGroup !== previousGroup) {
                optionShowGroupLabel = true;
                previousGroup = optionGroup;
            }
        }
        values.push({
            value: option[0].value,
            text: option[0].textContent.trim(),
            selected: option[0].selected,
            group: optionGroup,
            groupLabel: optionGroupLabel,
            showGroupLabel: optionShowGroupLabel,
            image: optionImage,
            icon: optionIcon,
            disabled: option[0].disabled,
            inputType: inputType,
            id: id,
            hasMedia: optionHasMedia,
            checkbox: inputType === 'checkbox',
            inputName: inputName,
            test: this
        });
    }

    // Item template/HTML
    if (!app._compiledTemplates.smartSelectItem) {
        app._compiledTemplates.smartSelectItem = t7.compile(app.params.smartSelectItemTemplate ||
            '{{#if showGroupLabel}}' +
            '
{{groupLabel}}
' +
            '{{/if}}' +
            '
' +
                '' +
                    '<input type="{{inputType}}" name="{{inputName}}" value="{{value}}" {{#if selected}}checked{{/if}}>' +
                    '{{#if hasMedia}}' +
                    '
' +
                        '{{#if checkbox}}{{/if}}' +
                        '{{#if icon}}{{/if}}' +
                        '{{#if image}}{{/if}}' +
                    '
' +
                    '{{/if}}' +
                    '
' +
                        '
{{text}}
' +
                    '
' +
                '' +
            '
'
        );
    }
    var smartSelectItemTemplate = app._compiledTemplates.smartSelectItem;

    var inputsHTML = '';
    if (!virtualList) {
        for (var j = 0; j < values.length; j++) {
            inputsHTML += smartSelectItemTemplate(values[j]);
        }
    }

    // Navbar HTML
    if (!app._compiledTemplates.smartSelectNavbar) {
        app._compiledTemplates.smartSelectNavbar = t7.compile(app.params.smartSelectNavbarTemplate ||
            '
' +
                '
' +
                    '{{leftTemplate}}' +
                    '
{{pageTitle}}
' +
                '
' +
            '
'
        );
    }
    var navbarHTML = app._compiledTemplates.smartSelectNavbar({
        pageTitle: pageTitle,
        backText: backText,
        closeText: closeText,
        openIn: openIn,
        navbarTheme: navbarTheme,
        inPopup: openIn === 'popup',
        inPage: openIn === 'page',
        leftTemplate: openIn === 'popup' ? app.params.smartSelectPopupCloseTemplate.replace(/{{closeText}}/g, closeText) : app.params.smartSelectBackTemplate.replace(/{{backText}}/g, backText)
    });

    // Determine navbar layout type - static/fixed/through
    var noNavbar = '', noToolbar = '', navbarLayout;
    if (openIn === 'page') {
        navbarLayout = 'static';
        if (smartSelect.parents('.navbar-through').length > 0) navbarLayout = 'through';
        if (smartSelect.parents('.navbar-fixed').length > 0) navbarLayout = 'fixed';
        noToolbar = smartSelect.parents('.page').hasClass('no-toolbar') ? 'no-toolbar' : '';
        noNavbar  = smartSelect.parents('.page').hasClass('no-navbar')  ? 'no-navbar'  : 'navbar-' + navbarLayout;
    }
    else {
        navbarLayout = 'fixed';
    }

    // Page Layout
    var pageName = 'smart-select-' + inputName;

    var useSearchbar = typeof smartSelect.data('searchbar') === 'undefined' ? app.params.smartSelectSearchbar : (smartSelect.data('searchbar') === 'true' ? true : false);
    var searchbarPlaceholder, searchbarCancel;

    if (useSearchbar) {
        searchbarPlaceholder = smartSelect.data('searchbar-placeholder') || 'Search';
        searchbarCancel = smartSelect.data('searchbar-cancel') || 'Cancel';
    }

    var searchbarHTML =   '<form class="searchbar" data-search-list=".smart-select-list-' + id + '" data-search-in=".item-title">' +
                            '
' +
                                '<input type="search" placeholder="' + searchbarPlaceholder + '">' +
                                '' +
                            '
' +
                            '' + searchbarCancel + '' +
                          '</form>' +
                          '

';

    var pageHTML =
        (navbarLayout === 'through' ? navbarHTML : '') +
        '
' +
        '
' +
             (navbarLayout === 'fixed' ? navbarHTML : '') +
             (useSearchbar ? searchbarHTML : '') +
        '
' +
               (navbarLayout === 'static' ? navbarHTML : '') +
        '
' +
        '
' +
                    (virtualList ? '' : inputsHTML) +
        '
' +
        '
' +
        '
' +
        '
' +
        '
';

    // Define popup
    var popup;

    // Event Listeners on new page
    function handleInputs(container) {
        if (virtualList) {
            var virtualListInstance = app.virtualList($(container).find('.virtual-list'), {
                items: values,
                template: smartSelectItemTemplate,
                height: virtualListItemHeight || undefined,
                searchByItem: function (query, index, item) {
                    if (item.text.toLowerCase().indexOf(query.trim()) >=0 ) return true;
                    return false;
                }
            });
            $(container).once(openIn === 'popup' ? 'closed': 'pageBeforeRemove', function () {
                if (virtualListInstance && virtualListInstance.destroy) virtualListInstance.destroy();
            });
        }
        $(container).on('change', 'input[name="' + inputName + '"]', function () {
            var input = this;
            var value = input.value;
            var optionText = [];
            if (input.type === 'checkbox') {
                var values = [];
                for (var i = 0; i < select.options.length; i++) {
                    var option = select.options[i];
                    if (option.value === value) {
                        option.selected = input.checked;
                    }
                    if (option.selected) {
                        optionText.push(option.textContent.trim());
                    }
                }
            }
            else {
                optionText = [smartSelect.find('option[value="' + value + '"]').text()];
                select.value = value;
            }

            $select.trigger('change');
            smartSelect.find('.item-after').text(optionText.join(', '));
            if (backOnSelect && inputType === 'radio') {
                if (openIn === 'popup') app.closeModal(popup);
                else view.router.back();
            }
        });
    }
    function pageInit(e) {
        var page = e.detail.page;
        if (page.name === pageName) {
            $(document).off('pageInit', pageInit);
            handleInputs(page.container);
        }
    }

    // Load content
    if (openIn === 'popup') {
        popup = app.popup(
                '
' +
                    '
' +
                        pageHTML +
                    '
' +
                '
'
                );
        app.initPage($(popup).find('.page'));
        handleInputs(popup);
    }
    else {
        $(document).on('pageInit', pageInit);
        view.router.load({content: pageHTML});
    }
};
<|endoftext|>


<commit_before>
var languages = [];
var paradigms = [];
var others = [];

$(function() {
	var i = 1;
	var resultDict = {0:{Reputation:5}};

	$.ajax({
		url: "http://localhost:8080/features/by_category",
		dataType: "json",
		async: false,
		success: function(data) {
			$.each(data['Languages'], function(i, v) {
				languages.push({id: v.name, tag: v.name});
			});
			$.each(data['Paradigms'], function(i, v) {
				paradigms.push({id: v.name, tag: v.name});
			});
			$.each(data['Others'], function(i, v) {
				others.push({id: v.name, tag: v.name});
			});
		}
	});

	function makeSliderHandler(idx, spinValue) {
		return function(ev) {
			var $sliderValue = ev.value;
			resultDict[''+idx][spinValue] = $sliderValue;
		};
	}

	function addRow(e) {
		var $spinValue = $(e.data.id1).val();
		if ($spinValue == '') {
			alert('Nothing selected!');
			return;
		}
		var sliderId = e.data.id2;
		var $tableId = $(e.data.id3);
		var inputId = e.data.id4;
		var sliderScript = document.createElement('script');
		var rowDict = {};

		if (!($spinValue in flattenObject(resultDict))) {
			sliderScript.text = "$('"+sliderId+i+"').slider({tooltip:'hide'});";
			$tableId.append('
'+
												$spinValue+
												'	'+
												'<input type="text" class="span2" value="4" id="'+
												inputId+i+
												'" style="">'+
												'
');
			$('#sl'+i+'')[0].appendChild(sliderScript);

			rowDict[$spinValue] = 5;
			resultDict[''+i] = rowDict;

			$(''+sliderId+i).slider().on('slideStop', makeSliderHandler(i, $spinValue));

			i++;
		}
	}

	function removeRow(e) {
		$(e.data.id).each(function() {
			//console.info(e.data.id);
			if ($('tbody', this).length > 0) {
				delete resultDict[$('tbody tr:last', this).attr('id')];
				$('tbody tr:last', this).remove();
			} else {
				delete resultDict[$('tr:last', this).attr('id')];
				$('tr:last', this).remove();
			}
		});
	}

	function flattenObject(ob) {
		var toReturn = {};

		for (var i in ob) {
			if (!ob.hasOwnProperty(i)) continue;

			if ((typeof ob[i]) == 'object') {
				var flatObject = flattenObject(ob[i]);
				for (var x in flatObject) {
					if (!flatObject.hasOwnProperty(x)) continue;
					toReturn[x] = flatObject[x];
				}
			} else {
				toReturn[i] = ob[i];
			}
		}
		return toReturn;
	}

	function format(item) {
		return item.tag;
	}

	function displayTableResults(data) {
		$('#resultTable').text('');
		$('#resultTable').append('

Users	Scores

');
		$.each(data.results, function(k, v) {
			$('#resultTable').append("
" +
							'' + v.ulogin +
							"	" +
							v.rank +
							"
");
		});
		$('#resultTable').append('
');
	}

	function displayElapsedTime(data) {
		$('#time').text('');
		$('#time').append("Search time: "+ data.elapsed_time + " milliseconds.");
	}

	/* Languages */
	$("#drop-lang-select").select2({
		placeholder: "Select a language",
		data: {results: languages, text: 'tag' },
		formatSelection: format,
		formatResult: format,
		allowClear: true
	});
	$('button#add-lang').click({
		id1:'#drop-lang-select', id2:'#slid-ln', id3:'#tab-lang', id4:'slid-ln'
	}, addRow);
	$('button#rm-lang').click({id:'#tab-lang'}, removeRow);

	/* Paradigms */
	$("#drop-pdgm-select").select2({
		placeholder: "Select a Paradigm",
		data: {results: paradigms, text: 'tag' },
		formatSelection: format,
		formatResult: format,
		allowClear: true
	});

	$('button#add-pdgm').click({
			id1:'#drop-pdgm-select', id2:'#slid-pm', id3:'#tab-pdgm', id4:'slid-pm'
		}, addRow);
	$('button#rm-pdgm').click({id:'#tab-pdgm'}, removeRow);

	/* Options */
	$("#drop-optn-select").select2({
	    placeholder: "Select an Option",
	    data: {results: others, text: 'tag' },
		formatSelection: format,
		formatResult: format,
	    allowClear: true
	});
	$('button#add-optn').click({
		id1:'#drop-optn-select', id2:'#slid-op', id3:'#tab-optn', id4:'slid-op'
	}, addRow);
	$('button#rm-optn').click({id:'#tab-optn'}, removeRow);

	/* Others */
	$('#slid-ot0').slider().on('slideStop', makeSliderHandler(0, 'Reputation'));

	/* Submission */
	$('form').submit(function() {
		//$('#result').text(JSON.stringify(flattenObject(resultDict)));
		$.ajax({
			url: 'http://localhost:8080/search/' + JSON.stringify(flattenObject(resultDict)),
			dataType: 'json',
			success: function(data) {
				//$('#result').text(JSON.stringify(data));
				displayTableResults(data);
				displayElapsedTime(data);
			}
		});
		return false;
	});
});
<commit_msg>query response time is given in seconds<commit_after>
var languages = [];
var paradigms = [];
var others = [];

$(function() {
	var i = 1;
	var resultDict = {0:{Reputation:5}};

	$.ajax({
		url: "http://localhost:8080/features/by_category",
		dataType: "json",
		async: false,
		success: function(data) {
			$.each(data['Languages'], function(i, v) {
				languages.push({id: v.name, tag: v.name});
			});
			$.each(data['Paradigms'], function(i, v) {
				paradigms.push({id: v.name, tag: v.name});
			});
			$.each(data['Others'], function(i, v) {
				others.push({id: v.name, tag: v.name});
			});
		}
	});

	function makeSliderHandler(idx, spinValue) {
		return function(ev) {
			var $sliderValue = ev.value;
			resultDict[''+idx][spinValue] = $sliderValue;
		};
	}

	function addRow(e) {
		var $spinValue = $(e.data.id1).val();
		if ($spinValue == '') {
			alert('Nothing selected!');
			return;
		}
		var sliderId = e.data.id2;
		var $tableId = $(e.data.id3);
		var inputId = e.data.id4;
		var sliderScript = document.createElement('script');
		var rowDict = {};

		if (!($spinValue in flattenObject(resultDict))) {
			sliderScript.text = "$('"+sliderId+i+"').slider({tooltip:'hide'});";
			$tableId.append('
'+
												$spinValue+
												'	'+
												'<input type="text" class="span2" value="4" id="'+
												inputId+i+
												'" style="">'+
												'
');
			$('#sl'+i+'')[0].appendChild(sliderScript);

			rowDict[$spinValue] = 5;
			resultDict[''+i] = rowDict;

			$(''+sliderId+i).slider().on('slideStop', makeSliderHandler(i, $spinValue));

			i++;
		}
	}

	function removeRow(e) {
		$(e.data.id).each(function() {
			//console.info(e.data.id);
			if ($('tbody', this).length > 0) {
				delete resultDict[$('tbody tr:last', this).attr('id')];
				$('tbody tr:last', this).remove();
			} else {
				delete resultDict[$('tr:last', this).attr('id')];
				$('tr:last', this).remove();
			}
		});
	}

	function flattenObject(ob) {
		var toReturn = {};

		for (var i in ob) {
			if (!ob.hasOwnProperty(i)) continue;

			if ((typeof ob[i]) == 'object') {
				var flatObject = flattenObject(ob[i]);
				for (var x in flatObject) {
					if (!flatObject.hasOwnProperty(x)) continue;
					toReturn[x] = flatObject[x];
				}
			} else {
				toReturn[i] = ob[i];
			}
		}
		return toReturn;
	}

	function format(item) {
		return item.tag;
	}

	function displayTableResults(data) {
		$('#resultTable').text('');
		$('#resultTable').append('

Users	Scores

');
		$.each(data.results, function(k, v) {
			$('#resultTable').append("
" +
							'' + v.ulogin +
							"	" +
							v.rank +
							"
");
		});
		$('#resultTable').append('
');
	}

	function displayElapsedTime(data) {
		$('#time').text('');
		$('#time').append("Search time: "+ data.elapsed_time + " seconds.");
	}

	/* Languages */
	$("#drop-lang-select").select2({
		placeholder: "Select a language",
		data: {results: languages, text: 'tag' },
		formatSelection: format,
		formatResult: format,
		allowClear: true
	});
	$('button#add-lang').click({
		id1:'#drop-lang-select', id2:'#slid-ln', id3:'#tab-lang', id4:'slid-ln'
	}, addRow);
	$('button#rm-lang').click({id:'#tab-lang'}, removeRow);

	/* Paradigms */
	$("#drop-pdgm-select").select2({
		placeholder: "Select a Paradigm",
		data: {results: paradigms, text: 'tag' },
		formatSelection: format,
		formatResult: format,
		allowClear: true
	});

	$('button#add-pdgm').click({
			id1:'#drop-pdgm-select', id2:'#slid-pm', id3:'#tab-pdgm', id4:'slid-pm'
		}, addRow);
	$('button#rm-pdgm').click({id:'#tab-pdgm'}, removeRow);

	/* Options */
	$("#drop-optn-select").select2({
	    placeholder: "Select an Option",
	    data: {results: others, text: 'tag' },
		formatSelection: format,
		formatResult: format,
	    allowClear: true
	});
	$('button#add-optn').click({
		id1:'#drop-optn-select', id2:'#slid-op', id3:'#tab-optn', id4:'slid-op'
	}, addRow);
	$('button#rm-optn').click({id:'#tab-optn'}, removeRow);

	/* Others */
	$('#slid-ot0').slider().on('slideStop', makeSliderHandler(0, 'Reputation'));

	/* Submission */
	$('form').submit(function() {
		//$('#result').text(JSON.stringify(flattenObject(resultDict)));
		$.ajax({
			url: 'http://localhost:8080/search/' + JSON.stringify(flattenObject(resultDict)),
			dataType: 'json',
			success: function(data) {
				//$('#result').text(JSON.stringify(data));
				displayTableResults(data);
				displayElapsedTime(data);
			}
		});
		return false;
	});
});
<|endoftext|>


<commit_before>/*
 * gui-builder - A simple WYSIWYG HTML5 app creator
 * Copyright (c) 2011, Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 */
"use strict";

// Layout view widget

(function($, undefined) {

    $.widget('gb.layoutView', {

        options: {
            model: null,
            iframe: null,
            contentDocument: null,
            customHeaders: {
                'meta': [
                    '<meta http-equiv="cache-control" content="no-cache">'
                ],
                'script': [
                    '',
                    ''
                ],
                'link': [
                    '<link href="src/css/composer.css" rel="stylesheet">'
                ]
            }
        },

        _create: function() {
            var o = this.options,
                e = this.element;

            o.designReset = this._designResetHandler;
            o.selectionChanged = this._selectionChangedHandler;
            o.activePageChanged = this._activePageChangedHandler;
            o.modelUpdated = this._modelUpdatedHandler;

            // FIXME: This should work, but $.extend of options seems to be
            //        creating a copy of the ADM, which will not containt the
            //        same nodes and events as the master
            //o.model = o.model || ADM || undefined;
            if (o.model) {
                this._bindADMEvents(o.model);
            }

            this.options.iframe = this.element.find('iframe');
            if (!this.options.iframe.length) {
                this.options.iframe = $('');
            }

            this.options.iframe.addClass(this.widgetName)
                .addClass('flex1')
                .appendTo(this.element);

            this.options.primaryTools = this._createPrimaryTools();
            this.options.secondaryTools = this._createSecondaryTools();

            this.options.contentDocument =
                $(this.options.iframe[0].contentDocument);

            $(window).resize(this, function(event) {
                var el = event.data.element,
                    doc = event.data.options.contentDocument,
                    iframe = event.data.options.iframe;
                // Force resize of the stage when containing window resizes
                el.height(el.parent().height());
                el.find('div').height(el.parent().height());
                // Force resize of the iframe when containing window resizes
                iframe.height(doc.height());
                iframe.css('min-height',
                            el.height() - 2
                            - parseFloat(iframe.css('margin-top'))
                            - parseFloat(iframe.css('margin-bottom'))
                            - parseFloat(iframe.css('padding-bottom'))
                            - parseFloat(iframe.css('padding-bottom')));
            });

            this.refresh(null, this);

            return this;
        },

        _setOption: function(key, value) {
            switch (key) {
                // Should this REALLY be done here, or plugin registration in
                // the "host"... using the functions mapped in widget options?
                case 'model':
                    this._unbindADMEvents();
                    this._bindADMEvents(value);
                    this._createDocument();
                    this.options.iframe.load(this, this._iframeLoaded);
                    break;
                default:
                    break;
            }
        },

        destroy: function() {
            // TODO: unbind any ADM event handlers
            $(this.element).find('.'+this.widgetName).remove();
            this.options.primaryTools.remove();
            this.options.secondaryTools.remove();
        },

        refresh: function(event, widget) {
            var name;
            widget = widget || event && event.data || this;
            name = (event)?(event.name)?event.name:event.type:'';

            if (!widget.loaded) return;

            if (!event) {
                widget._serializeADMDesignToDOM();
            } else if (event.type === 'load') {
                widget._serializeADMDesignToDOM();
            } else if (event.name === 'designReset') {
                widget._serializeADMDesignToDOM();
            } else if (event.name === 'modelUpdated') {
                widget._serializeADMDesignToDOM();
/* FIXME: Calling serializeADMSubtreeToDom is not actually forcing the
          the DOM to update, but it should work...

                switch (event.type) {
                    case 'nodeAdded':
                    case 'nodeRemoved':
                        serializeADMSubtreeToDOM(event.parent, null,
                                                 widget._renderer);
                        break;
                    case 'nodeMoved':
                        serializeADMSubtreeToDOM(event.oldParent, null,
                                                 widget._renderer);
                        serializeADMSubtreeToDOM(event.newParent, null,
                                                 widget._renderer);
                        break;
                    case 'propertyChanged':
                        serializeADMSubtreeToDOM(event.node, null,
                                                 widget._renderer);
                        break;
                    default:
                        console.warn(widget.widgetName,
                                     ':: Unexpected modelUpdate type:',
                                     event.type);
                        return;
                        break;
                }
*/
            } else {
                console.warn(widget.widgetName,':: Unexpected event:',name);
                return;
            }

            if (widget.options.contentDocument.length) {
                widget.options.contentDocument[0].defaultView
                    .postMessage('reload', '*');
            } else {
                console.error(widget.widgetName, ':: Missing contentDocument');
            }

            // Refresh our cache of iframe sortables
            widget._refreshSortables();
        },

        // Private functions
        _getSortables: function(update) {
            if (update) {
                this._sortables = this.options.contentDocument
                                      .find('.nrc-sortable-container');
            } else {
                this._sortables = this._sortables||this.options.contentDocument
                                      .find('.nrc-sortable-container');
            }
            return this._sortables;
        },

        _refreshSortables: function() {
            // Force a re-search for sortables in the iframe doc
            var s = this._getSortables(true);

            // Associate the palette items with these sortables
            $(':gb-paletteView .ui-draggable').draggable('option', {
                connectToSortable: s,
            });
        },

        _iframeLoaded: function(event) {
            event.data.loaded = true;
            event.data.refresh(null, event.data);
        },

        _createPrimaryTools: function() {
            var doc, html, classes, selector,
                commands = ['undo', 'redo', 'cut', 'copy', 'paste'];

            classes = "buttonStyle primary-tools ui-state-default";
            html = $('
').addClass('hbox').hide();
            $.each(commands, function (index, command) {
                $('<button/>').addClass(classes)
                    .attr('id', 'btn' + command)
                    .appendTo(html);
            });

            doc = $((this.element)[0].ownerDocument);
            selector = "button.primary-tools"
            doc.delegate(selector, "click", jQuery.proxy(function (event) {
                var model = this.options.model;
                if (model) {
                    switch (event.currentTarget.id) {
                    case "btnundo":  model.undo();  break;
                    case "btnredo":  model.redo();  break;
                    case "btncut":   model.cut();   break;
                    case "btncopy":  model.copy();  break;
                    case "btnpaste": model.paste(); break;
                    default:
                        console.warn("Unhandled click on primary tool");
                        break;
                    }
                }
                else {
                    console.warn("No model while attempting undo");
                }
            }, this));

            return html;
        },

        _createSecondaryTools: function() {
            return $(null);
        },

        _bindADMEvents: function(a) {
            var o = this.options,
                d = this.designRoot;

            if (a) {
                o.model = a;

                if (o.designReset) {
                    a.bind("designReset", o.designReset, this);
                }
                if (o.selectionChanged) {
                    a.bind("selectionChanged", o.selectionChanged, this);
                }
                if (o.activePageChanged) {
                    a.bind("activePageChanged", o.activePageChanged, this);
                }

                // Since model changed, need to call our designReset hander
                // to sync up the ADMDesign modelUpdated event handler
                if (o.designReset) {
                    o.designReset({design: a.getDesignRoot()}, this);
                }
            }
        },

        _unbindADMEvents: function() {
            var o = this.options,
                a = this.options.model,
                d = this.designRoot;

            // First unbind our ADMDesign modelUpdated handler, if any...
            if (d && o.modelUpdated) {
                d.designRoot.unbind("modelUpdated", o.modelUpdated, this);
            }

            // Now unbind all ADM model event handlers, if any...
            if (a) {
                if (o.designReset) {
                    a.unbind("designReset", o.designReset, this);
                }
                if (o.selectionChanged) {
                    a.unbind("selectionChanged", o.selectionChanged, this);
                }
                if (o.activePageChanged) {
                    a.unbind("activePageChanged", o.activePageChanged, this);
                }
            }
        },

        _designResetHandler: function(event, widget) {
            var d = event && event.design, o;

            widget = widget || this;
            o = widget.options;
            d = d || o.model.getDesignRoot();

            // Do nothing if the new ADMDesign equals our currently cached one
            if (d === widget.designRoot) {
                return;
            }

            // First, unbind existing modelUpdated hander, if any...
            if (widget.designRoot && o.modelUpdated) {
                widget.designRoot.unbind("modelUpdated", o.modelUpdated,widget);
            }

            // Next, bind to modelUpdated events from new ADMDesign, if any...
            if (d && o.modelUpdated) {
                d.bind("modelUpdated", o.modelUpdated, widget);
            }

            // Then, cache the new ADMDesign reference with this instance
            widget.designRoot = d;

            // Finally, redraw our view since the ADMDesign root has changed
            widget.refresh(event, widget);
        },

        _selectionChangedHandler: function(event, widget) {
            var uid;
            widget = widget || this;

            // Always un-style currently selected nodes
            widget.options.contentDocument.find('.ui-selected')
                .removeClass('ui-selected');

            // Only apply selection style changes on valid nodes
            if (!event || (!event.uid && !event.node)) {
                return;
            }

            // Normally, ADM node id is provided in event.uid
            uid = event && event.uid;
            // Fallback is to try event.node.getUid()
            uid = uid || (event.node)?event.node.getUid():null;

            if (uid) {
                widget.options.contentDocument
                    .find('.adm-node[data-uid=\''+uid+'\']')
                    .not('[data-role=\'page\']')
                    .addClass('ui-selected').first().each(function() {
                        // Scroll selected node into view
                        this.scrollIntoViewIfNeeded();
                    });
            }
        },

        _activePageChangedHandler: function(event, widget) {
            var win,
                newPage = event && event.page,
                id = newPage && newPage.getProperty('id');

            widget = widget || this;

            // Only change if new page is valid
            if (!newPage) {
                return;
            }

            win = widget.options.contentDocument[0].defaultView;

            if (win && win.$ && win.$.mobile) {
                win.$.mobile.changePage("#"+id, {transition: "none"});
            }
        },

        _modelUpdatedHandler: function(event, widget) {
            var win;

            widget = widget || this;

            widget.refresh(event, widget);

            win = widget.options.contentDocument[0].defaultView;
            if (win && win.$ && win.$.mobile) {
                win.$.mobile.activePage.page('destroy');
                win.$.mobile.activePage.page();
            } else {
                console.error(widget.widgetName, ':: Missing contentDocument');
            }
        },

        _createDocument: function() {
            var contents, doc;

            if (!this.designRoot) return;

            doc = this.options.contentDocument[0];
            doc.open();
            contents = this._serializeFramework(this.designRoot);
            doc.writeln(contents);
            doc.close();
        },

        _serializeFramework: function() {
            var start, end, ret, headers;

            headers = this._getCustomHeaders();

            start = '<!DOCTYPE html>\n <title>Page Title</title>\n';
            end = "\n\n\n";

            if (headers && headers.length > 0) {
                ret = start + headers.join('\n') + end;
            } else {
                ret = start + end;
            }

            return ret;
        },

        // Great assumptions are being made here that the incoming default
        // headers are already "sorted" and in the order in which they should
        // be inserted into the  node of the document being created...
        _getCustomHeaders: function() {
            var dh = $.gb.getDefaultHeaders(),   // default headers
                ch = this.options.customHeaders, // our custom headers
                m, s;

            $.each(dh, function(idx) {
                if (/<meta/.test(this)) {
                    m = idx+1; // Insert our Meta after LAST one
                    return;
                }
                if (/',
                    ''
                ],
                'link': [
                    '<link href="src/css/composer.css" rel="stylesheet">'
                ]
            }
        },

        _create: function() {
            var o = this.options,
                e = this.element;

            o.designReset = this._designResetHandler;
            o.selectionChanged = this._selectionChangedHandler;
            o.activePageChanged = this._activePageChangedHandler;
            o.modelUpdated = this._modelUpdatedHandler;

            // FIXME: This should work, but $.extend of options seems to be
            //        creating a copy of the ADM, which will not containt the
            //        same nodes and events as the master
            //o.model = o.model || ADM || undefined;
            if (o.model) {
                this._bindADMEvents(o.model);
            }

            this.options.iframe = this.element.find('iframe');
            if (!this.options.iframe.length) {
                this.options.iframe = $('');
            }

            this.options.iframe.addClass(this.widgetName)
                .addClass('flex1')
                .appendTo(this.element);

            this.options.primaryTools = this._createPrimaryTools();
            this.options.secondaryTools = this._createSecondaryTools();

            this.options.contentDocument =
                $(this.options.iframe[0].contentDocument);

            $(window).resize(this, function(event) {
                var el = event.data.element,
                    doc = event.data.options.contentDocument,
                    iframe = event.data.options.iframe;
                // Force resize of the stage when containing window resizes
                el.height(el.parent().height());
                el.find('div').height(el.parent().height());
                // Force resize of the iframe when containing window resizes
                iframe.height(doc.height());
                iframe.css('min-height',
                            el.height() - 2
                            - parseFloat(iframe.css('margin-top'))
                            - parseFloat(iframe.css('margin-bottom'))
                            - parseFloat(iframe.css('padding-bottom'))
                            - parseFloat(iframe.css('padding-bottom')));
            });

            this.refresh(null, this);

            return this;
        },

        _setOption: function(key, value) {
            switch (key) {
                // Should this REALLY be done here, or plugin registration in
                // the "host"... using the functions mapped in widget options?
                case 'model':
                    this._unbindADMEvents();
                    this._bindADMEvents(value);
                    this._createDocument();
                    this.options.iframe.load(this, this._iframeLoaded);
                    break;
                default:
                    break;
            }
        },

        destroy: function() {
            // TODO: unbind any ADM event handlers
            $(this.element).find('.'+this.widgetName).remove();
            this.options.primaryTools.remove();
            this.options.secondaryTools.remove();
        },

        refresh: function(event, widget) {
            var name;
            widget = widget || event && event.data || this;
            name = (event)?(event.name)?event.name:event.type:'';

            if (!widget.loaded) return;

            if (!event) {
                widget._serializeADMDesignToDOM();
            } else if (event.type === 'load') {
                widget._serializeADMDesignToDOM();
            } else if (event.name === 'designReset') {
                widget._serializeADMDesignToDOM();
            } else if (event.name === 'modelUpdated') {
                widget._serializeADMDesignToDOM();
/* FIXME: Calling serializeADMSubtreeToDom is not actually forcing the
          the DOM to update, but it should work...

                switch (event.type) {
                    case 'nodeAdded':
                    case 'nodeRemoved':
                        serializeADMSubtreeToDOM(event.parent, null,
                                                 widget._renderer);
                        break;
                    case 'nodeMoved':
                        serializeADMSubtreeToDOM(event.oldParent, null,
                                                 widget._renderer);
                        serializeADMSubtreeToDOM(event.newParent, null,
                                                 widget._renderer);
                        break;
                    case 'propertyChanged':
                        serializeADMSubtreeToDOM(event.node, null,
                                                 widget._renderer);
                        break;
                    default:
                        console.warn(widget.widgetName,
                                     ':: Unexpected modelUpdate type:',
                                     event.type);
                        return;
                        break;
                }
*/
            } else {
                console.warn(widget.widgetName,':: Unexpected event:',name);
                return;
            }

            if (widget.options.contentDocument.length) {
                widget.options.contentDocument[0].defaultView
                    .postMessage('reload', '*');
            } else {
                console.error(widget.widgetName, ':: Missing contentDocument');
            }

            // Refresh our cache of iframe sortables
            widget._refreshSortables();
        },

        // Private functions
        _getSortables: function(update) {
            if (update) {
                this._sortables = this.options.contentDocument
                                      .find('.nrc-sortable-container');
            } else {
                this._sortables = this._sortables||this.options.contentDocument
                                      .find('.nrc-sortable-container');
            }
            return this._sortables;
        },

        _refreshSortables: function() {
            // Force a re-search for sortables in the iframe doc
            var s = this._getSortables(true);

            // Associate the palette items with these sortables
            $(':gb-paletteView .ui-draggable').draggable('option', {
                connectToSortable: s,
            });
        },

        _iframeLoaded: function(event) {
            event.data.loaded = true;
            event.data.refresh(null, event.data);
        },

        _createPrimaryTools: function() {
            var doc, html, classes, selector,
                commands = ['undo', 'redo', 'cut', 'copy', 'paste'];

            classes = "buttonStyle primary-tools ui-state-default";
            html = $('
').addClass('hbox').hide();
            $.each(commands, function (index, command) {
                $('<button/>').addClass(classes)
                    .attr('id', 'btn' + command)
                    .appendTo(html);
            });

            doc = $((this.element)[0].ownerDocument);
            selector = "button.primary-tools"
            doc.delegate(selector, "click", jQuery.proxy(function (event) {
                var model = this.options.model;
                if (model) {
                    switch (event.currentTarget.id) {
                    case "btnundo":  model.undo();  break;
                    case "btnredo":  model.redo();  break;
                    case "btncut":   model.cut();   break;
                    case "btncopy":  model.copy();  break;
                    case "btnpaste": model.paste(); break;
                    default:
                        console.warn("Unhandled click on primary tool");
                        break;
                    }
                }
                else {
                    console.warn("No model while attempting undo");
                }
            }, this));

            return html;
        },

        _createSecondaryTools: function() {
            return $(null);
        },

        _bindADMEvents: function(a) {
            var o = this.options,
                d = this.designRoot;

            if (a) {
                o.model = a;

                if (o.designReset) {
                    a.bind("designReset", o.designReset, this);
                }
                if (o.selectionChanged) {
                    a.bind("selectionChanged", o.selectionChanged, this);
                }
                if (o.activePageChanged) {
                    a.bind("activePageChanged", o.activePageChanged, this);
                }

                // Since model changed, need to call our designReset hander
                // to sync up the ADMDesign modelUpdated event handler
                if (o.designReset) {
                    o.designReset({design: a.getDesignRoot()}, this);
                }
            }
        },

        _unbindADMEvents: function() {
            var o = this.options,
                a = this.options.model,
                d = this.designRoot;

            // First unbind our ADMDesign modelUpdated handler, if any...
            if (d && o.modelUpdated) {
                d.designRoot.unbind("modelUpdated", o.modelUpdated, this);
            }

            // Now unbind all ADM model event handlers, if any...
            if (a) {
                if (o.designReset) {
                    a.unbind("designReset", o.designReset, this);
                }
                if (o.selectionChanged) {
                    a.unbind("selectionChanged", o.selectionChanged, this);
                }
                if (o.activePageChanged) {
                    a.unbind("activePageChanged", o.activePageChanged, this);
                }
            }
        },

        _designResetHandler: function(event, widget) {
            var d = event && event.design, o;

            widget = widget || this;
            o = widget.options;
            d = d || o.model.getDesignRoot();

            // Do nothing if the new ADMDesign equals our currently cached one
            if (d === widget.designRoot) {
                return;
            }

            // First, unbind existing modelUpdated hander, if any...
            if (widget.designRoot && o.modelUpdated) {
                widget.designRoot.unbind("modelUpdated", o.modelUpdated,widget);
            }

            // Next, bind to modelUpdated events from new ADMDesign, if any...
            if (d && o.modelUpdated) {
                d.bind("modelUpdated", o.modelUpdated, widget);
            }

            // Then, cache the new ADMDesign reference with this instance
            widget.designRoot = d;

            // Finally, redraw our view since the ADMDesign root has changed
            widget.refresh(event, widget);
        },

        _selectionChangedHandler: function(event, widget) {
            var uid;
            widget = widget || this;

            // Always un-style currently selected nodes
            widget.options.contentDocument.find('.ui-selected')
                .removeClass('ui-selected');

            // Only apply selection style changes on valid nodes
            if (!event || (!event.uid && !event.node)) {
                return;
            }

            // Normally, ADM node id is provided in event.uid
            uid = event && event.uid;
            // Fallback is to try event.node.getUid()
            uid = uid || (event.node)?event.node.getUid():null;

            if (uid) {
                widget.options.contentDocument
                    .find('.adm-node[data-uid=\''+uid+'\']')
                    .not('[data-role=\'page\']')
                    .addClass('ui-selected').first().each(function() {
                        // Scroll selected node into view
                        this.scrollIntoViewIfNeeded();
                    });
            }
        },

        _activePageChangedHandler: function(event, widget) {
            var win,
                newPage = event && event.page,
                id = newPage && newPage.getProperty('id');

            widget = widget || this;

            // Only change if new page is valid
            if (!newPage) {
                return;
            }

            win = widget.options.contentDocument[0].defaultView;

            if (win && win.$ && win.$.mobile) {
                win.$.mobile.changePage("#"+id, {transition: "none"});
            }
        },

        _modelUpdatedHandler: function(event, widget) {
            var win;

            widget = widget || this;

            widget.refresh(event, widget);

            win = widget.options.contentDocument[0].defaultView;
            if (win && win.$ && win.$.mobile) {
                var aPage = widget.options.model.getActivePage();
                if (aPage) {
                    win.$.mobile.changePage(win.$('#' + aPage.getProperty('id')));
                } else {
                    win.$.mobile.initializePage();
                }
            } else {
                console.error(widget.widgetName, ':: Missing contentDocument');
            }
        },

        _createDocument: function() {
            var contents, doc;

            if (!this.designRoot) return;

            doc = this.options.contentDocument[0];
            doc.open();
            contents = this._serializeFramework(this.designRoot);
            doc.writeln(contents);
            doc.close();
        },

        _serializeFramework: function() {
            var start, end, ret, headers;

            headers = this._getCustomHeaders();

            start = '<!DOCTYPE html>\n <title>Page Title</title>\n';
            end = "\n\n\n";

            if (headers && headers.length > 0) {
                ret = start + headers.join('\n') + end;
            } else {
                ret = start + end;
            }

            return ret;
        },

        // Great assumptions are being made here that the incoming default
        // headers are already "sorted" and in the order in which they should
        // be inserted into the  node of the document being created...
        _getCustomHeaders: function() {
            var dh = $.gb.getDefaultHeaders(),   // default headers
                ch = this.options.customHeaders, // our custom headers
                m, s;

            $.each(dh, function(idx) {
                if (/<meta/.test(this)) {
                    m = idx+1; // Insert our Meta after LAST one
                    return;
                }
                if (/


<commit_before>/* http://upload.wikimedia.org/wikipedia/commons/0/01/2007-02-20_time_zones.svg */
/*
  In the northern emisphere, january is in winter and july is in summer.
  In the southern emisphere, january is in summer and july is in winter.
  A daylight saving time offset is always -1, so standard time is always
  the greatest of two offsets.
*/
(function() {
  var jsk = {
    /******* PROPERTIES *******/
    breakingMonth : 0,
    testMonth0Offset : null,
    testMonth6Offset : null,
    timeSepator : "",
    /******* PRIVATE *******/
    getDateOffset : function getDate(month) {
      return new Date((new Date()).getFullYear(), month, 0).getTimezoneOffset();
    },
    getMonth0Offset : function() {
      return jsk.testMonth0Offset !== null ?
        jsk.testMonth0Offset :
        jsk.getDateOffset(jsk.breakingMonth);
    },
    getMonth6Offset : function() {
      return jsk.testMonth6Offset !== null ?
        jsk.testMonth6Offset :
        jsk.getDateOffset(jsk.breakingMonth+6);
    },
    offsetToString : function(offset, timeSeparator) {
      timeSeparator = timeSeparator || jsk.timeSeparator || "";

      var parts = [];

      var st = offset/60.0;
      parts.push(st >= 0 ? "+" : "-");

      var hour = Math.floor(Math.abs(st));
      parts.push((hour <= 9 ? "0" : "") + hour);

      parts.push(timeSeparator);

      var min = Math.abs(st%1.0)*60;
      parts.push((min <= 9 ? "0" : "") + min);

      return parts.join("");
    },
    /******* PUBLIC *******/
    // Force some test offsets
    testOffset : function testOffset(month0Offset, month6Offset) {
      jsk.testMonth0Offset = month0Offset;
      jsk.testMonth6Offset = month6Offset;
    },
    // the timezone has daylight saving
    hasDst : function() {
      return jsk.st() != jsk.dst();
    },
    // Returns the standard time offset (inverted)
    invertedSt : function invertedSt() {
      return Math.max(jsk.getMonth0Offset(), jsk.getMonth6Offset());
    },
    // Returns the daylight saving time offset (inverted)
    invertedDst : function invertedDst() {
      return Math.min(jsk.getMonth0Offset(), jsk.getMonth6Offset());
    },
    // Returns the standard time offset
    st : function st() {
      return 0-jsk.invertedSt();
    },
    // Returns standard to string
    stToString : function(timeSeparator) {
      return jsk.offsetToString(jsk.st(), timeSeparator);
    },
    // Returns the standard time offset
    dst : function dst() {
      return 0-jsk.invertedDst();
    },
    // Returns daylight saving to string
    dstToString : function(timeSeparator) {
      return jsk.offsetToString(jsk.dst(), timeSeparator);
    },
    iHateTheLastComma : true // this line exists because I hate the last comma
  };

  // Creates the base namespaces
  if (typeof(window.javascriptKataDotCom) == "undefined") { window.javascriptKataDotCom = {}; }
  if (typeof(window.jsKata) == "undefined") { window.jsKata = window.javascriptKataDotCom; }
  if (typeof(window.jsk) == "undefined") { window.jsk = window.javascriptKataDotCom; }
  if (typeof(window._) == "undefined") { window._ = window.javascriptKataDotCom; }

  window.javascriptKataDotCom.timezone = jsk;
  window.javascriptKataDotCom.tz = jsk;
})();
<commit_msg>error on precommit<commit_after>/* http://upload.wikimedia.org/wikipedia/commons/0/01/2007-02-20_time_zones.svg */
/*
  In the northern emisphere, january is in winter and july is in summer.
  In the southern emisphere, january is in summer and july is in winter.
  A daylight saving time offset is always -1, so standard time is always
  the greatest of two offsets.
*/
(function() {
  var jsk = {
    /******* PROPERTIES *******/
    breakingMonth : 0,
    testMonth0Offset : null,
    testMonth6Offset : null,
    timeSepator : "",
    /******* PRIVATE *******/
    getDateOffset : function getDate(month) {
      return new Date((new Date()).getFullYear(), month, 0).getTimezoneOffset();
    },
    getMonth0Offset : function() {
      return jsk.testMonth0Offset !== null ?
        jsk.testMonth0Offset :
        jsk.getDateOffset(jsk.breakingMonth);
    },
    getMonth6Offset : function() {
      return jsk.testMonth6Offset !== null ?
        jsk.testMonth6Offset :
        jsk.getDateOffset(jsk.breakingMonth+6);
    },
    offsetToString : function(offset, timeSeparator) {
      timeSeparator = timeSeparator || jsk.timeSeparator || "";

      var parts = [];

      var st = offset/60.0;
      parts.push(st >= 0 ? "+" : "-");

      var hour = Math.floor(Math.abs(st));
      parts.push((hour <= 9 ? "0" : "") + hour);

      parts.push(timeSeparator);

      var min = Math.abs(st%1.0)*60;
      parts.push((min <= 9 ? "0" : "") + min);

      return parts.join("");
    },
    /******* PUBLIC *******/
    // Force some test offsets
    testOffset : function testOffset(month0Offset, month6Offset) {
      jsk.testMonth0Offset = month0Offset;
      jsk.testMonth6Offset = month6Offset;
    },
    // the timezone has daylight saving
    hasDst : function() {
      return jsk.st() != jsk.dst();
    },
    // Returns the standard time offset (inverted)
    invertedSt : function invertedSt() {
      return Math.max(jsk.getMonth0Offset(), jsk.getMonth6Offset());
    },
    // Returns the daylight saving time offset (inverted)
    invertedDst : function invertedDst() {
      return Math.min(jsk.getMonth0Offset(), jsk.getMonth6Offset());
    },
    // Returns the standard time offset
    st : function st() {
      return 0-jsk.invertedSt();
    },
    // Returns standard to string
    stToString : function(timeSeparator) {
      return jsk.offsetToString(jsk.st(), timeSeparator);
    },
    // Returns the standard time offset
    dst : function dst() {
      return 0-jsk.invertedDst();
    },
    // Returns daylight saving to string
    dstToString : function(timeSeparator) {
      return jsk.offsetToString(jsk.dst(), timeSeparator);
    },
    iHateTheLastComma : true // this line exists because I hate the last comma
  };

  // Creates the base namespaces
  if (typeof(window.javascriptKataDotCom) == "undefined") { window.javascriptKataDotCom = {}; }
  if (typeof(window.jsKata) == "undefined") { window.jsKata = window.javascriptKataDotCom; }
  if (typeof(window.jsk) == "undefined") { window.jsk = window.javascriptKataDotCom; }
  if (typeof(window._) == "undefined") { window._ = window.javascriptKataDotCom; }

  window.javascriptKataDotCom.timezone = jsk;
  window.javascriptKataDotCom.tz = jsk;
})()
<|endoftext|>


<commit_before>/*******************************************************************************
Open Source Initiative OSI - The MIT License (MIT):Licensing
[OSI Approved License]
The MIT License (MIT)

Copyright (c) Sean McGregor

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

*******************************************************************************/
var privly = {
  //Matches:
  //              http://
  //              https://
  //                        priv.ly/textAndNumbers/any/number/of/times
  //
  //also matches localhost:3000
  privlyReferencesRegex: /\b(https?:\/\/){0,1}(priv\.ly|localhost:3000)(\/posts)(\/\w*){1,}\b/gi,

  // Takes a domain with an optional http(s) in front and returns a fully formed domain name
  makeHref: function(domain)
  {
    var hasHTTPRegex = /^((https?)\:\/\/)/i;
    if(!hasHTTPRegex.test(domain))
        domain = "http://" + domain;
    return domain;
  },

  //Make plain text links into anchor elements
  createLinks: function()
  {
      /*************************************************************************
      Inspired by Linkify script:
        http://downloads.mozdev.org/greasemonkey/linkify.user.js

      Originally written by Anthony Lieuallen of http://arantius.com/
      Licensed for unlimited modification and redistribution as long as
      this notice is kept intact.
      **************************************************************************/

      var excludeParents = ["a", "applet", "button", "code", "form",
                             "input", "option", "script", "select", "meta",
                             "style", "textarea", "title", "div","span"];
      var excludedParentsString = excludeParents.join(" or parent::");
      var xpathExpression = ".//text()[not(parent:: " + excludedParentsString +")]";

      textNodes = document.evaluate(xpathExpression, document.body, null,
                                    XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

      for(var i=0; i < textNodes.snapshotLength; i++){
          item = textNodes.snapshotItem(i);

          var itemText = item.nodeValue;

          privly.privlyReferencesRegex.lastIndex = 0;
          if(privly.privlyReferencesRegex.test(itemText)){
              var span = document.createElement("span");
              var lastLastIndex = 0;
              privly.privlyReferencesRegex.lastIndex = 0;
              for(var results = null; results = privly.privlyReferencesRegex.exec(itemText); ){
                  var href = results[0];
                  span.appendChild(document.createTextNode(itemText.substring(lastLastIndex, results.index)));

                  var text = (href.indexOf(" ")==0)?href.substring(1):href;

                  var href = privly.makeHref(text);

                  var a = document.createElement("a");
                  a.setAttribute("href", href);
                  a.appendChild(document.createTextNode(text.substring(0,4).toLowerCase()+text.substring(4)));
                  if(href.indexOf(" ")==0)
                      span.appendChild(document.createTextNode(" "));
                  span.appendChild(a);
                  lastLastIndex = privly.privlyReferencesRegex.lastIndex;
              }
              span.appendChild(document.createTextNode(itemText.substring(lastLastIndex)));
              item.parentNode.replaceChild(span, item);
          }
      }
  },

  //Kill default link behaviour on Privly Links
  makePassive: function(anchor)
  {
    //Preventing the default link behavior
    anchor.addEventListener("mousedown", function(e){
        e.cancelBubble = true;
        e.stopPropagation();
        e.preventDefault();
        privly.replaceLink(anchor);
      },
      true);
  },

  //Checks link attributes and text for privly links without the proper href attribute.
  //Twitter and other hosts change links so they can collect click events.
  correctIndirection: function()
  {
    var anchors = document.links;
    var i = anchors.length;
    while (i--){
      var a = anchors[i];

      if(a.href && (a.href.indexOf("priv.ly/posts/") == -1 || a.href.indexOf("priv.ly/posts/") > 9))
      {
        if (privly.privlyReferencesRegex.test(a.innerHTML)) {
          // If the href is not present or is on a different domain
          privly.privlyReferencesRegex.lastIndex = 0;
          var results = privly.privlyReferencesRegex.exec(a.innerHTML);
          var newHref = privly.makeHref(results[0]);
          a.setAttribute("href", newHref);
        }
      }
    }
  },

  nextAvailableFrameID: 0,

  // Replace an anchor element with its referenced content.
  replaceLink: function(object)
  {
    var iFrame = document.createElement('iframe');
    iFrame.setAttribute("frameborder","0");
    iFrame.setAttribute("vspace","0");
    iFrame.setAttribute("hspace","0");
    iFrame.setAttribute("name","privlyiframe");
    iFrame.setAttribute("width","100%");
    iFrame.setAttribute("marginwidth","0");
    iFrame.setAttribute("marginheight","0");
    iFrame.setAttribute("height","1px");
    iFrame.setAttribute("src",object.href + ".iframe?frame_id=" + privly.nextAvailableFrameID);
    iFrame.setAttribute("id","ifrm"+privly.nextAvailableFrameID);
    iFrame.setAttribute("frameborder","0");
    privly.nextAvailableFrameID++;
    iFrame.setAttribute("style","width: 100%; height: 32px; overflow: hidden;");
    iFrame.setAttribute("scrolling","no");
    iFrame.setAttribute("overflow","hidden");

    object.parentNode.replaceChild(iFrame, object);
  },

  //Replace all Privly links with their iframe
  replaceLinks: function()
  {
    var anchors = document.links;
    var i = anchors.length;
    elements = document.getElementsByTagName("privModeElement");
    if(elements != null && elements.length != 0){
      this.extensionMode = elements[0].getAttribute('mode');
    }
    else{
      /* if there is no privModeElement tag in DOM, then the extension is probably
      * disabled. so set the mode accordingly.
      */
      this.extensionMode = 3;
    }
    while (--i >= 0){
      var a = anchors[i];
      this.privlyReferencesRegex.lastIndex = 0;
      if(a.href && this.privlyReferencesRegex.test(a.href))
      {
      	var exclude = a.getAttribute("privly");
        if(exclude == null || exclude != "exclude"){
          if(this.extensionMode == 0){
            this.replaceLink(a);
          }
          else if(this.extensionMode == 1){
            a.innerHTML = 'Privly is currently experiencing heavy traffic. Click here to see privly content';
            a.onmousedown = function(event){
              event.cancelBubble = true;
              event.stopPropagation();
              event.preventDefault();
              privly.replaceLink(a);
            };
          }
          else if(this.extensionMode == 2){
            a.innerHTML = "Privly is in sleep mode so it can catch up with demand. The content may still be viewable by clicking this link";
          }
          else if(this.extensionMode == 3){
            a.innerHTML = "Privly temporarily disabled all requests to its servers. Please try again later.";
          }
        }
      }
    }
  },

  //resize the iframe using a posted message
  resizeIframe: function(message){

    if(message.origin !== "https://priv.ly" && message.origin !== "http://localhost:3000")
      return;

    var data = message.data.split(",");

    var iframe = document.getElementById("ifrm"+data[0]);
    iframe.style.height = data[1]+'px';
  },

  //indicates whether the extension shoud immediatly replace all Privly
  //links it encounters
  extensionMode: 0,

  //prevents DOMNodeInserted from sending hundreds of extension runs
  runPending: false,

  //prep the page and replace the links if it is in active mode
  run: function()
  {
    //create and correct the links pointing
    //to Privly content
    privly.createLinks();
    privly.correctIndirection();

    //replace all available links on load, if in active mode,
    //otherwise replace all links default behavior
    privly.replaceLinks();
  },

  //runs privly once then registers the update listener
  //for dynamic pages
  listeners: function(){
    //don't recursively replace links
    if(document.URL.indexOf('priv.ly') != -1 || document.URL.indexOf('localhost:3000') != -1)
      return;

    //The content's iframe will post a message to the hosting document. This listener sets the height
    //of the iframe according to the messaged height
    window.addEventListener("message", privly.resizeIframe, false, true);

    privly.runPending=true;
    setTimeout(
      function(){
        privly.runPending=false;
        privly.run();
      },
      100);

    //Everytime the page is updated via javascript, we have to check
    //for new Privly content. This might not be supported on other platforms
    document.addEventListener("DOMNodeInserted", function(event) {
      //we check the page a maximum of two times a second
      if(privly.runPending)
        return;
      privly.runPending=true;

      setTimeout(
        function(){
          privly.runPending=false;
          privly.run();
        },
        500);
    });
  },

  // cross platform onload event
  // won't attach anything on IE
  // on macintosh systems.
  addEvent: function(obj, evType, fn){
    if (obj.addEventListener){
      obj.addEventListener(evType, fn, false);
      return true;
    }
    else if (obj.attachEvent){
      var r = obj.attachEvent("on"+evType, fn);
      return r;
    }
    else {
      return false;
    }
  }
}

privly.addEvent(window, 'load', privly.listeners);

<commit_msg>solved privly href on attribute other than href<commit_after>/*******************************************************************************
Open Source Initiative OSI - The MIT License (MIT):Licensing
[OSI Approved License]
The MIT License (MIT)

Copyright (c) Sean McGregor

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

*******************************************************************************/
var privly = {
  //Matches:
  //              http://
  //              https://
  //                        priv.ly/textAndNumbers/any/number/of/times
  //
  //also matches localhost:3000
  privlyReferencesRegex: /\b(https?:\/\/){0,1}(priv\.ly|localhost:3000)(\/posts)(\/\w*){1,}\b/gi,

  // Takes a domain with an optional http(s) in front and returns a fully formed domain name
  makeHref: function(domain)
  {
    var hasHTTPRegex = /^((https?)\:\/\/)/i;
    if(!hasHTTPRegex.test(domain))
        domain = "http://" + domain;
    return domain;
  },

  //Make plain text links into anchor elements
  createLinks: function()
  {
      /*************************************************************************
      Inspired by Linkify script:
        http://downloads.mozdev.org/greasemonkey/linkify.user.js

      Originally written by Anthony Lieuallen of http://arantius.com/
      Licensed for unlimited modification and redistribution as long as
      this notice is kept intact.
      **************************************************************************/

      var excludeParents = ["a", "applet", "button", "code", "form",
                             "input", "option", "script", "select", "meta",
                             "style", "textarea", "title", "div","span"];
      var excludedParentsString = excludeParents.join(" or parent::");
      var xpathExpression = ".//text()[not(parent:: " + excludedParentsString +")]";

      textNodes = document.evaluate(xpathExpression, document.body, null,
                                    XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

      for(var i=0; i < textNodes.snapshotLength; i++){
          item = textNodes.snapshotItem(i);

          var itemText = item.nodeValue;

          privly.privlyReferencesRegex.lastIndex = 0;
          if(privly.privlyReferencesRegex.test(itemText)){
              var span = document.createElement("span");
              var lastLastIndex = 0;
              privly.privlyReferencesRegex.lastIndex = 0;
              for(var results = null; results = privly.privlyReferencesRegex.exec(itemText); ){
                  var href = results[0];
                  span.appendChild(document.createTextNode(itemText.substring(lastLastIndex, results.index)));

                  var text = (href.indexOf(" ")==0)?href.substring(1):href;

                  var href = privly.makeHref(text);

                  var a = document.createElement("a");
                  a.setAttribute("href", href);
                  a.appendChild(document.createTextNode(text.substring(0,4).toLowerCase()+text.substring(4)));
                  if(href.indexOf(" ")==0)
                      span.appendChild(document.createTextNode(" "));
                  span.appendChild(a);
                  lastLastIndex = privly.privlyReferencesRegex.lastIndex;
              }
              span.appendChild(document.createTextNode(itemText.substring(lastLastIndex)));
              item.parentNode.replaceChild(span, item);
          }
      }
  },

  //Kill default link behaviour on Privly Links
  makePassive: function(anchor)
  {
    //Preventing the default link behavior
    anchor.addEventListener("mousedown", function(e){
        e.cancelBubble = true;
        e.stopPropagation();
        e.preventDefault();
        privly.replaceLink(anchor);
      },
      true);
  },

  //Checks link attributes and text for privly links without the proper href attribute.
  //Twitter and other hosts change links so they can collect click events.
  correctIndirection: function()
  {
    var anchors = document.links;
    var i = anchors.length;
    while (i--){
      var a = anchors[i];

      if(a.href && (a.href.indexOf("priv.ly/posts/") == -1 || a.href.indexOf("priv.ly/posts/") > 9))
      {
        //check if Privly is in the body of the text
        privly.privlyReferencesRegex.lastIndex = 0;
        if (privly.privlyReferencesRegex.test(a.innerHTML)) {
          // If the href is not present or is on a different domain
          privly.privlyReferencesRegex.lastIndex = 0;
          var results = privly.privlyReferencesRegex.exec(a.innerHTML);
          var newHref = privly.makeHref(results[0]);
          a.setAttribute("href", newHref);
        }

        //check if Privly was moved to another attribute
        for (var y = 0; y < a.attributes.length; y++) {
          var attrib = a.attributes[y];
          if (attrib.specified == true) {
            privly.privlyReferencesRegex.lastIndex = 0;
            if (privly.privlyReferencesRegex.test(attrib.value)) {
              a.setAttribute("href", attrib.value);
            }
          }
        }
      }
      privly.privlyReferencesRegex.lastIndex = 0;
    }
  },

  nextAvailableFrameID: 0,

  // Replace an anchor element with its referenced content.
  replaceLink: function(object)
  {
    var iFrame = document.createElement('iframe');
    iFrame.setAttribute("frameborder","0");
    iFrame.setAttribute("vspace","0");
    iFrame.setAttribute("hspace","0");
    iFrame.setAttribute("name","privlyiframe");
    iFrame.setAttribute("width","100%");
    iFrame.setAttribute("marginwidth","0");
    iFrame.setAttribute("marginheight","0");
    iFrame.setAttribute("height","1px");
    iFrame.setAttribute("src",object.href + ".iframe?frame_id=" + privly.nextAvailableFrameID);
    iFrame.setAttribute("id","ifrm"+privly.nextAvailableFrameID);
    iFrame.setAttribute("frameborder","0");
    privly.nextAvailableFrameID++;
    iFrame.setAttribute("style","width: 100%; height: 32px; overflow: hidden;");
    iFrame.setAttribute("scrolling","no");
    iFrame.setAttribute("overflow","hidden");

    object.parentNode.replaceChild(iFrame, object);
  },

  //Replace all Privly links with their iframe
  replaceLinks: function()
  {
    var anchors = document.links;
    var i = anchors.length;
    elements = document.getElementsByTagName("privModeElement");
    if(elements != null && elements.length != 0){
      this.extensionMode = elements[0].getAttribute('mode');
    }
    else{
      /* if there is no privModeElement tag in DOM, then the extension is probably
      * disabled. so set the mode accordingly.
      */
      this.extensionMode = 3;
    }
    while (--i >= 0){
      var a = anchors[i];
      this.privlyReferencesRegex.lastIndex = 0;
      if(a.href && this.privlyReferencesRegex.test(a.href))
      {
      	var exclude = a.getAttribute("privly");
        if(exclude == null || exclude != "exclude"){
          if(this.extensionMode == 0){
            this.replaceLink(a);
          }
          else if(this.extensionMode == 1){
            a.innerHTML = 'Privly is currently experiencing heavy traffic. Click here to see privly content';
            a.onmousedown = function(event){
              event.cancelBubble = true;
              event.stopPropagation();
              event.preventDefault();
              privly.replaceLink(a);
            };
          }
          else if(this.extensionMode == 2){
            a.innerHTML = "Privly is in sleep mode so it can catch up with demand. The content may still be viewable by clicking this link";
          }
          else if(this.extensionMode == 3){
            a.innerHTML = "Privly temporarily disabled all requests to its servers. Please try again later.";
          }
        }
      }
    }
  },

  //resize the iframe using a posted message
  resizeIframe: function(message){

    if(message.origin !== "https://priv.ly" && message.origin !== "http://localhost:3000")
      return;

    var data = message.data.split(",");

    var iframe = document.getElementById("ifrm"+data[0]);
    iframe.style.height = data[1]+'px';
  },

  //indicates whether the extension shoud immediatly replace all Privly
  //links it encounters
  extensionMode: 0,

  //prevents DOMNodeInserted from sending hundreds of extension runs
  runPending: false,

  //prep the page and replace the links if it is in active mode
  run: function()
  {
    //create and correct the links pointing
    //to Privly content
    privly.createLinks();
    privly.correctIndirection();

    //replace all available links on load, if in active mode,
    //otherwise replace all links default behavior
    privly.replaceLinks();
  },

  //runs privly once then registers the update listener
  //for dynamic pages
  listeners: function(){
    //don't recursively replace links
    if(document.URL.indexOf('priv.ly') != -1 || document.URL.indexOf('localhost:3000') != -1)
      return;

    //The content's iframe will post a message to the hosting document. This listener sets the height
    //of the iframe according to the messaged height
    window.addEventListener("message", privly.resizeIframe, false, true);

    privly.runPending=true;
    setTimeout(
      function(){
        privly.runPending=false;
        privly.run();
      },
      100);

    //Everytime the page is updated via javascript, we have to check
    //for new Privly content. This might not be supported on other platforms
    document.addEventListener("DOMNodeInserted", function(event) {
      //we check the page a maximum of two times a second
      if(privly.runPending)
        return;
      privly.runPending=true;

      setTimeout(
        function(){
          privly.runPending=false;
          privly.run();
        },
        500);
    });
  },

  // cross platform onload event
  // won't attach anything on IE
  // on macintosh systems.
  addEvent: function(obj, evType, fn){
    if (obj.addEventListener){
      obj.addEventListener(evType, fn, false);
      return true;
    }
    else if (obj.attachEvent){
      var r = obj.attachEvent("on"+evType, fn);
      return r;
    }
    else {
      return false;
    }
  }
}

privly.addEvent(window, 'load', privly.listeners);

<|endoftext|>