1//font control panel plugin 2(function ($) { 3 /*globals document, setTimeout, setInterval, clearTimeout, window, alert, prompt, confirm, navigator, jQuery, console, $, ajaxproxy, location, tinyMCE, fontBlogUrl, fontBlogName, clearInterval, fontPluginVersion, ajaxproxy, ajaxproxy2, ajaxproxy3*/ 4 $.fontPlugin = function (el, options) { 5 var self = this; 6 self.$el = $(el); 7 self.el = el; 8 self.baseSelector = '#' + self.$el.attr('id'); 9 self.$el.data('fontPlugin', self); 10 //modal windows array 11 self.modals = []; 12 self.options = options; 13 self.options = $.extend({}, $.fontPlugin.defaultOptions, self.options); 14 self.version = fontPluginVersion; 15 self.settingFields = []; 16 self.effectSliders = []; 17 /* 18 Initialize 19 */ 20 self.init = function () { 21 self.detectMode(); 22 self.showLoading(); 23 self.loadSettings(); 24 if (!$.fn.on) { 25 alert('WARNING: You are using an old Wordpress version. It is not guaranteed that the plugin will work. The oldest tested Wordpress version is 3.1 but at least 3.3.1 is recommended.'); 26 } 27 }; 28 /* 29 * 30 * MARKUP 31 * 32 */ 33 /* 34 * Create presets panel 35 */ 36 self.createPresetsPanel = function () { 37 var i, 38 presetName, 39 presetId, 40 field, 41 paramObj, 42 upgrade, 43 modalOptions, 44 modal; 45 /* 46 PRESETS 47 */ 48 modalOptions = { 49 id: 'presetsPanel', 50 name: 'stdSettings', 51 title: 'Font ' + self.version, 52 nobar: false, 53 left: '10px', 54 top: '50px', 55 width: '98px', 56 show: true 57 }; 58 modal = self.createNewModal(modalOptions); 59 modal.show(); 60 self.$presets = modal; 61 //add presets list 62 self.settingFields.presets = $('<fieldset id="presetsDropdownFieldset"><label>Selections<select id="presetsDropdown" name="presetsDropdown"></select></label></fieldset>'); 63 self.$presetsDropdown = self.settingFields.presets.find('select'); 64 self.$presets.append(self.settingFields.presets); 65 self.$presetsDropdown.bind('change', function () { 66 self.loadPreset($(this).val()); 67 self.scrollToSelection(); 68 }); 69 //populate presets list 70 for (i = 0; i < self.options.presets.length; i += 1) { 71 presetName = self.options.presets[i].name; 72 presetId = i; 73 self.$presetsDropdown.append('<option value="' + presetId + '">' + presetName + '</option>'); 74 } 75 // Delete current preset 76 self.settingFields.deletePreset = $('<button id="deletePreset" title="Delete">x</button>'); 77 self.settingFields.presets.append(self.settingFields.deletePreset); 78 self.settingFields.deletePreset.on('click', function () { 79 self.deleteCurrentPreset(); 80 }); 81 // Rename current preset 82 self.settingFields.renamePreset = $('<button id="renamePreset">Rename</button>'); 83 self.settingFields.presets.append(self.settingFields.renamePreset); 84 self.settingFields.renamePreset.on('click', function () { 85 self.renamePreset(); 86 }); 87 }; 88 /** 89 Like? Yes or No 90 **/ 91 self.addLikeYesNo = function () { 92 //add like not/like 93 self.$yesno = $('<div class="yesno">Like the plugin?<br><a href="http://fontsforweb.com/purchase/howtosupport?url=' + fontBlogUrl + '&name=' + fontBlogName + '" class="overlay_url yesbutton" data-upgrade="true">Yes!</a> or <a href="http://www.fontsforweb.com/contact/support" class="overlay_url nobutton">No</a></div>'); 94 self.$yesno.appendTo(self.$actions); 95 self.$yesno.css({ 96 'color': '#fff', 97 'font-size': '10px', 98 'text-align': 'right', 99 'font-weight': 'bold', 100 'float': 'left', 101 'margin-right': '10px' 102 }); 103 self.$yesno.find('a').css({ 104 'font-size': '10px', 105 'color': '#fff' 106 }); 107 }; 108 /* 109 * Create appearance panel - size and color 110 * 111 * @returns {unresolved} 112 */ 113 self.createAppearancePanel = function () { 114 var i, 115 presetName, 116 presetId, 117 field, 118 paramObj, 119 saveButton, 120 upgrade, 121 modalOptions, 122 modal, 123 settingWindows; 124 /* 125 SELECTORS 126 */ 127 //get standard fields in a new window 128 modalOptions = { 129 id: 'appearancePanel', 130 name: 'stdSettings', 131 title: 'Size and color settings', 132 left: '0', 133 top: '0px', 134 width: '100%', 135 nobar: true, 136 show: true 137 }; 138 modal = self.createNewModal(modalOptions); 139 self.$apr = modal; 140 self.$apr.hide(); 141 //create a fieldset 142 self.$standardFields = $('<div id="appearanceStandardFields"></div>').appendTo(modal); 143 //get standard fields in a new window 144 modalOptions = { 145 title: 'Extended settings', 146 left: '0', 147 top: '0' 148 }; 149 modal = self.createNewModal(modalOptions); 150 self.$extendedFields = $('<div id="appearanceExtendedFields"></div>').appendTo(modal); 151 //get extended fields not ready 152 /*var switcher = $('<a href="#" id="showExtendedFields">Load extended fields from FontsForWeb.com</a>').appendTo(self.$apr); 153 self.$extendedFields.hide(); 154 switcher.on('click', function () { self.$extendedFields.slideToggle(); self.loadExtendedFields(); return false; });*/ 155 /* 156 Add all setting fields 157 */ 158 for (i = 0; i < self.options.settingFields.length; i += 1) { 159 field = self.options.settingFields[i]; 160 paramObj = {}; 161 paramObj.field = field; 162 paramObj.type = 'lite'; 163 self.addSettingsField(paramObj); 164 } 165 //add window opening buttons 166 settingWindows = $('<fieldset id="settingsButtons"></fieldset>'); 167 //bind toggle modal 168 $('body').on('click', '.toggleModal', function () { 169 if (self.mode === 'global') { 170 var selector = self.currentPreset.selector; 171 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 172 alert('First pick an element from the page to customize it.'); 173 return; 174 } 175 } else if (self.mode === 'postPage') { 176 //VERSION FOR POST PAGE 177 //get selection 178 var selection = tinyMCE.activeEditor.selection.getContent(); 179 //only apply if something is selected 180 if (!selection) { 181 alert('Make a selection in the editor window first.'); 182 return; 183 } 184 } 185 var modalName = $(this).attr('data-modal-name'); 186 self.toggleModal(modalName); 187 }); 188 $('body').on('mousedown click', '.getApiKey', function () { 189 $(this).attr('href', 'http://fontsforweb.com/purchase?url=' + fontBlogUrl); 190 $(this).attr('target', '_blank'); 191 }); 192 //add keyup to change field 193 self.getField('selector').bind('keyup', function () { 194 $(this).trigger('change'); 195 self.hoverSelector = self.currentPreset.selector; 196 self.hoverHighlightCurrent(); 197 }); 198 }; 199 self.createActionButtons = function () { 200 var saveButton, 201 actions, 202 closeMod; 203 //add buttons fieldset 204 actions = $('<fieldset id="actionsFieldset"></fieldset>'); 205 closeMod = $('<a class="closeModal" href="#">x</a>'); 206 actions.append(closeMod); 207 self.$actions = actions; 208 closeMod.click(function () { 209 self.$presets.hide(); 210 self.$apr.hide(); 211 }); 212 //add different fields buttons 213 var fontfaceSettings = $('<button id="fontfaceSettings">Font</button>').prependTo(self.$apr); 214 //add actions 215 fontfaceSettings.on('click', function () { 216 if (self.mode === 'global') { 217 var selector = self.currentPreset.selector; 218 if (selector.indexOf('ELEMENT NOW') !== -1 || selector.indexOf('PICK ELEMENT') !== -1) { 219 alert('First pick an element from the page to customize it.'); 220 return; 221 } 222 } else if (self.mode === 'postPage') { 223 //VERSION FOR POST PAGE 224 //get selection 225 var selection = tinyMCE.activeEditor.selection.getContent(); 226 //only apply if something is selected 227 if (!selection) { 228 alert('Make a selection in the editor window first.'); 229 return; 230 } 231 } 232 self.showFontsBrowser(); 233 }); 234 // PRO settings window 235 var proSettings = $('<a href="http://fontsforweb.com/purchase/pluginupgradesubscribe?url=' + fontBlogUrl + '&name=' + fontBlogName + '" class="overlay_url" id="upgradeToProButton" data-upgrade="true">Pro settings</a>').appendTo(self.$apr); 236 // extra fields 237 var extrafieldsSettings = $('<button id="extrafieldsSettings" class="toggleModal" data-modal-name="extrafields">PRO</button>').appendTo(self.$apr); 238 // hide extra fields 239 extrafieldsSettings.hide(); 240 // effects button 241 var effects = $('<button id="effectsButton" class="toggleModal" data-modal-name="effects">Effects</button>').appendTo(self.$apr); 242 // styles button 243 var styles = $('<button id="stylesButton" class="toggleModal" data-modal-name="styles">Styles</button>').appendTo(self.$apr); 244 245 //add save button 246 saveButton = $('<button id="fontSaveSettings">Save settings</button>').appendTo(actions); 247 saveButton.click(function (e) { 248 // blink few fimes 249 saveButton.fadeTo(500, 0.3).fadeTo(500, 1).fadeTo(500, 0.3).fadeTo(500, 1).fadeTo(500, 0.3).fadeTo(500, 1).fadeTo(500, 0.3).fadeTo(500, 1).fadeTo(500, 0.3).fadeTo(500, 1); 250 //unbind click 251 saveButton.unbind('click'); 252 saveButton.css({ 253 'cursor': 'wait' 254 }); 255 self.saveSettings();
256 }); 257 self.$apr.append(actions); 258 }; 259 /* 260 * API FUNCTIONS 261 */ 262 /* 263 * check if api key is present in the database 264 */ 265 self.checkForApikey = function () { 266 self.xhrPost({ 267 url: self.options.FFW_baseUrl + '/api/getkey', 268 data: { 269 blogurl: fontBlogUrl, 270 apikey: self.options.apikey, 271 version: self.version 272 } 273 }, function (data) { 274 if (!data || data.success !== 'true') { 275 if (console !== undefined) { 276 console.log(data.message); 277 } 278 alert('An error has occured and the plugin is not working. If you\'re working on local server, make sure \n that your computer has an internet connection.'); 279 } else { 280 if(data.keytype === 'FREE' && self.loaded === true) { 281 return; 282 } 283 self.loadEffectsPanel(data.effects); 284 if (data.extended.length) { 285 self.loadExtendedFields(data.extended); 286 $('#upgradeToProButton').remove(); 287 $('#extrafieldsSettings').show(); 288 clearInterval(self.checkForApikeyInterval); 289 } 290 self.loadStylesPanel(data.styles); 291 self.options.apikey = data.apikey; 292 self.loaded = true; 293 } 294 }); 295 }; 296 //setup api key interval 297 self.setupApikeyCheckingInterval = function () { 298 if (!self.checkForApikeyInterval) { 299 self.checkForApikeyInterval = setInterval(function () { 300 self.checkForApikey(); 301 }, 5000); 302 } 303 }; 304 /* 305 * SETTINGS - SAVE AND LOAD 306 */ 307 /* 308 * Load settings from wordpress options 309 */ 310 self.loadSettings = function () { 311 var data = { 312 action: 'get_font_settings' 313 }; 314 $.ajax({
315 type: "POST", 316 url: ajaxproxy, 317 data: data, 318 success: function (response) { 319 // json is coming parsed so no $.parseJSON(response); 320 try { 321 response = $.parseJSON(response); 322 } catch (e) { 323 self.tryAnotherAjaxproxy(); 324 return; 325 } 326 //console.log(self.options); 327 if (response && response.settingFields) { 328 self.options = $.extend({}, response, self.options); 329 } else { 330 self.tryAnotherAjaxproxy(); 331 return; 332 } 333 self.loadConfig(); 334 }, 335 error: function (response) { 336 self.tryAnotherAjaxproxy(); 337 } 338 }); 339 }; 340 self.tryAnotherAjaxproxy = function () { 341 alert('Sorry, but the plugin couldn\'t start. Please contact your server administrator to allow AJAX use. Power users: Use console (F12 in Chrome) to see what else could be the problem.'); 342 return; 343 /*if (ajaxproxy === ajaxproxy3) { 344 alert('Sorry, but the plugin couldn\'t start. Please contact your server administrator to allow AJAX use. Power users: Use console (F12 in Chrome) to see what else could be the problem.'); 345 return; 346 } 347 else if (ajaxproxy === ajaxproxy2) { 348 ajaxproxy = ajaxproxy3; 349 } else { 350 ajaxproxy = ajaxproxy2; 351 }*/ 352 self.loadSettings(); 353 }; 354 355 /** 356 * 357 * continue loading with config file 358 * 359 **/ 360 self.loadConfig = function () { 361 // try loading the plugin 362 try { 363 //console.log(self.options); 364 self.hideLoading(); 365 // markup 366 self.createPresetsPanel(); 367 self.createAppearancePanel(); 368 self.createActionButtons(); 369 self.loadPreset(0); 370 self.bindShowCategoriesAction(); 371 self.bindShowFontsAction(); 372 self.bindLinkOverlay(); 373 self.setFontOnclick(); 374 self.initUploadForm(); 375 self.adaptOptionsToMode(); 376 self.addLikeYesNo(); 377 self.checkForApikey(); 378 if (self.options.presets && self.options.presets[1]) { 379 self.loadPreset(1); 380 } 381 } catch (e) { 382 console.dir(e); 383 alert('The plugin will not work'); 384 } 385 }, 386 /* 387 * Save settings by ajax 388 * 389 * @returns {unresolved} 390 */ 391 self.saveSettings = function () { 392 var savingOptions = {}, 393 data; 394 if (self.mode === 'postPage') { 395 alert('Click on "Update" or "Publish" to save'); 396 return; 397 } 398 self.$presets.hide(); 399 self.$apr.hide(); 400 self.showLoading(); 401 savingOptions.settingFields = self.options.settingFields; 402 savingOptions.presets = self.options.presets; 403 savingOptions.apikey = self.options.apikey; 404 data = { 405 action: 'set_font_settings', 406 fontPluginSettings: JSON.stringify(savingOptions) 407 }; 408 $.post(ajaxproxy, data, function (response) { 409 if (response.success !== 'true') { 410 alert('Error: ' + response.message); 411 return; 412 } else { 413 window.onbeforeunload = null; 414 location.reload(true); 415 } 416 }, 'json').error(function (xhr, textStatus, errorThrown) { 417 alert("Unknown error: \n" + xhr.responseText); 418 }); 419 }; 420 //update internal settings - value 421 self.updateSettings = function (settingName, value) { 422 if (self.mode !== 'global') { 423 return; 424 } 425 self.options.presets[self.currentPresetNo][settingName] = value; 426 }; 427 //update internal settings - css value 428 self.updateCssSettings = function (settingName, value) { 429 if (self.mode !== 'global') { 430 return; 431 } 432 self.options.presets[self.currentPresetNo].styles[settingName] = value; 433 }; 434 /* 435 update selected element CSS 436 global - update element from selector 437 postPage - update selected text 438 */ 439 self.updateSelectedElement = function (settingName, value) { 440 var selection, 441 selector, 442 selectorValid, 443 $selectorContents, 444 element, 445 node, 446 justInsertedClass, 447 newSpan, 448 newHTML, 449 inserted, 450 $tempDiv; 451 if (!value || value == 'px') return; 452 if (self.mode === 'global') { 453 //VERSION FOR GENERAL SETTINGS PAGE 454 selector = self.currentPreset.selector; 455 //exit when default selector 456 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 457 return; 458 } 459 //get the element from iframe or current page 460 if ($('#header1preview').length) { 461 element = $('#header1preview').contents().find(selector); 462 } else { 463 element = $(selector); 464 } 465 element.each(function () { 466 //CSS exceptions and general action 467 switch (settingName) { 468 case 'rotate': 469 $(this).style('-webkit-transform', 'rotate(' + value + 'deg)', 'important'); 470 $(this).style('-moz-transform', 'rotate(' + value + 'deg)', 'important'); 471 $(this).style('-o-transform', 'rotate(' + value + 'deg)', 'important'); 472 $(this).style('-ms-transform', 'rotate(' + value + 'deg)', 'important'); 473 $(this).style('transform', 'rotate(' + value + 'deg)', 'important'); 474 break; 475 //general action 476 default: 477 $(this).style(settingName, value, 'important'); 478 } 479 }); 480 } else if (self.mode === 'postPage') { 481 //VERSION FOR POST PAGE 482 //get selection 483 selection = tinyMCE.activeEditor.selection.getContent(); 484 //only apply if something is selected 485 if (!selection) { 486 return; 487 } 488 //selectorValid - validate selector created from selected text. 489 //required because for example "." with nothing following breaks function execution 490 selectorValid = true; 491 try { 492 $selectorContents = $(selection); 493 } catch (e) { 494 selectorValid = false; 495 } 496 if (selectorValid && $selectorContents.length > 1) { 497 selectorValid = false; 498 } 499 //get node 500 node = tinyMCE.activeEditor.selection.getNode(); 501 if (selectorValid && ($.trim($(node).html()) === $.trim(selection) || $.trim($(node).html()) === $.trim($(selection).html()))) { 502 //console.log('already isolated'); 503 tinyMCE.activeEditor.dom.setStyle(node, settingName, value); 504 } else { 505 //console.log('isolating: ' + $(node).html() + ' - ' + selection);
506 justInsertedClass = 'inserted' + Math.floor(Math.random() * 10000); 507 newSpan = $('<span id="' + justInsertedClass + '">' + selection + '</span>'); 508 newSpan.css(settingName, value); 509 $tempDiv = $('<div>').append(newSpan.clone()); 510 $tempDiv.find('*').each(function () { 511 //if ($(this).inlineStyle && $(this).inlineStyle(settingName)) { 512 $(this).css(settingName, value); 513 //} 514 }); 515 //get span html together with span itself 516 newHTML = $tempDiv.html(); 517 inserted = tinyMCE.activeEditor.selection.setContent(newHTML); 518 tinyMCE.activeEditor.selection.select(tinyMCE.activeEditor.dom.select('span#' + justInsertedClass)[0]); 519 } 520 } 521 }; 522 /* 523 * 524 * FIELDS 525 * 526 */ 527 /* 528 * Load extended fields 529 */ 530 self.loadExtendedFields = function (data) { 531 var i, 532 field, 533 paramObj, 534 modalOptions, 535 modal; 536 //create a new modal for it 537 modalOptions = { 538 name: 'extrafields', 539 title: 'Pro options', 540 left: '5px', 541 top: '40px', 542 width: '270px' 543 }; 544 modal = self.createNewModal(modalOptions); 545 for (i = 0; i < data.length; i += 1) { 546 field = data[i]; 547 paramObj = {}; 548 paramObj.field = field; 549 paramObj.type = 'extrafields'; 550 self.addSettingsField(paramObj); 551 } 552 self.reloadPreset(); 553 }; 554 /* 555 * Add a field to selected place 556 * paramObj 557 * 558 * @returns {unresolved} 559 * .field - field definition - no data or assignations here 560 * .settings - contain field settings 561 */ 562 self.addSettingsField = function (paramObj, loadDefaults) { 563 var field = paramObj.field, 564 thisField, 565 thisInput, 566 i, 567 manipulator, 568 fieldset, 569 fieldParam, 570 container, 571 inputFields = []; 572 if (loadDefaults === undefined) { 573 loadDefaults = false; 574 } 575 //add support for multi value field 576 if (field.settingType === 'cssmultival') { 577 if (!paramObj.target) { 578 //create a new modal for it 579 var modalOptions = { 580 name: field.name, 581 title: field.label, 582 left: '0', 583 top: '50px', 584 width: '270px' 585 }; 586 container = self.createNewModal(modalOptions); 587 } else { 588 container = paramObj.target; 589 } 590 //create a fieldset 591 fieldset = self.settingFields[field.name] = $('<fieldset id="' + field.name + 'Fieldset"></fieldset>'); 592 //add fieldset to extended fields 593 container.append(fieldset); 594 var XYSliderOptions = false; 595 //add all controls 596 for (i = 0; i < field.values.length; i += 1) { 597 fieldParam = field.values[i]; 598 var privateInputField = thisInput; 599 var subfield = fieldParam; 600 //create a field with label around 601 var manipulator = $('<label>' + subfield.label + '<a class="resetField">reset</a><input type="' + subfield.type + '" title="' + subfield.settingName + '"></label>'); 602 manipulator.appendTo(fieldset); 603 privateInputField = manipulator.find('input'); 604 privateInputField.data('fieldInfo', subfield); 605 privateInputField.data('settings', paramObj.settings); 606 // ADD CORRESPONDING ENTRY IN FIELD SETTINGS 607 if (paramObj.settings && !paramObj.settings.params) { 608 var params = {}; 609 paramObj.settings.params = params; 610 } 611 //append field to extended list 612 fieldset.append(thisField); 613 //extend field with whatever 614 privateInputField = self.extendField(privateInputField, subfield.extendWith); 615 // if handle is assigned add actions 616 if (subfield.handle) { 617 if (!XYSliderOptions) { 618 XYSliderOptions = {}; 619 XYSliderOptions.actions = []; 620 } 621 // action can be x, y, deg, distance 622 // stop - last action don't trigger input change 623 XYSliderOptions.id = privateInputField.data('settings').uniqueId; 624 inputFields[subfield.handle.linkTo] = privateInputField; 625 } 626 } 627 var XYSlider = false; 628 if (XYSliderOptions) { 629 var rand = Math.random() * 1000, 630 stop = true;
631 // if xy slider set then add it 632 XYSliderOptions.label = field.label; 633 if (field.invertX) { 634 XYSliderOptions.invertX = true; 635 } 636 XYSliderOptions.settingName = paramObj.settings.uniqueId; 637 var Mathra = Math.random(); 638 XYSliderOptions.actions = function (x, y, deg, distance) { 639 inputFields['x'] ? ( 640 inputFields['x'].val(x), 641 inputFields['x'].trigger('change', stop) 642 ) : false; 643 inputFields['y'] ? ( 644 inputFields['y'].val(y), 645 inputFields['y'].trigger('change', stop) 646 ) : false; 647 inputFields['deg'] ? ( 648 inputFields['deg'].val(deg), 649 inputFields['deg'].trigger('change', stop) 650 ) : false; 651 inputFields['distance'] ? ( 652 inputFields['distance'].val(distance / 2), 653 inputFields['distance'].trigger('change', stop) 654 ) : false; 655 }; 656 //XYSliderOptions.target = paramObj.target; 657 var $XYSlider = self.currentElement.XYSlider(XYSliderOptions); 658 XYSlider = $XYSlider.data('XYSlider'); 659 //add to effect handles 660 self.effectSliders[paramObj.settings.uniqueId] = XYSlider.$handleHolder; 661 if (!paramObj.settings.enabled) { 662 self.effectSliders[paramObj.settings.uniqueId].hide(); 663 } 664 } 665 //bind action to the inputs 666 var inputs = fieldset.find('input'); 667 //bind change to inputs 668 inputs.bind('change click keyup', function (event, stop) { 669 // settings 670 var settings = $(this).data('settings'), 671 fieldInfo = $(this).data('fieldInfo'), 672 storage = $(this).data('storage'), 673 val = $(this).val(), 674 XYSliderX, 675 XYSliderY; 676 if (stop === undefined) stop = false; 677 // add arrow up - down support 678 //37 - left, 38 - up, 39 - right, 40 - down 679 if (event.which === 38 && !isNaN(val)) { 680 $(this).val(parseFloat(val) + 1); 681 $(this).trigger('change'); 682 return false; 683 } else if (event.which === 40 && !isNaN(val)) { 684 $(this).val(parseFloat(val) - 1); 685 $(this).trigger('change'); 686 return false; 687 } 688 // save param setting 689 settings.params[fieldInfo.settingName] = val; 690 691 //console.log($(this).data('fieldInfo').settingName + ', ' + $(this).val() + ', ' + ($(this).data('fieldInfo').unit || '')) 692 //get values of all siblings and create one value for the element 693 var completeValue = ''; 694 inputs.each(function () { 695 var fieldInfo = $(this).data('fieldInfo'), 696 unit = ''; 697 if (fieldInfo.unit) { 698 unit = fieldInfo.unit; 699 } 700 //get field info 701 completeValue += ' ' + $(this).val() + unit; 702 if ($(this).val() == '') { 703 $(this).val(fieldInfo['default']); 704 } 705 if (XYSlider && !stop && fieldInfo.handle) { 706 if (fieldInfo.handle.linkTo === 'x') { 707 XYSliderX = $(this).val(); 708 } else if (fieldInfo.handle.linkTo === 'y') { 709 XYSliderY = $(this).val(); 710 } 711 } 712 }); 713 // when changing value of the input move the handle too 714 // if this input is linked to a handle 715 if (XYSlider && !stop && fieldInfo.handle) { 716 // get "linked to" of a handle and move x or y accordingly 717 if (XYSliderX && XYSliderY) {
718 XYSlider.setPosition(XYSliderX, XYSliderY); 719 } else if (XYSliderX) { 720 XYSlider.setPosition(XYSliderX, false); 721 } else if (XYSliderY) { 722 XYSlider.setPosition(false, XYSliderY); 723 } 724 } 725 // if this is text-shadow 726 if (field.settingName === 'text-shadow') { 727 //var effect = self.getElementsEffect(settings.uniqueId); 728 completeValue = completeValue.replace(/, +$/, ''); 729 var XYSliderValues = XYSlider.getCurrentValues(); 730 self.drawEffects({ 731 completeValue: completeValue, 732 target: self.currentElement, 733 color: settings.params.color, 734 x: -XYSliderValues.x, 735 y: XYSliderValues.y, 736 deg: 180 - XYSliderValues.deg * -1, 737 distance: XYSliderValues.distance, 738 effectId: settings.uniqueId, 739 effectsList: ['textShadow'] 740 }); 741 } else if (field.settingName === 'text-stroke') { 742 // go through all settings 743 //var effect = self.getElementsEffect(settings.uniqueId); 744 completeValue = completeValue.replace(/, +$/, ''); 745 //var XYSliderValues = XYSlider.getCurrentValues();
746 self.drawEffects({ 747 target: self.currentElement, 748 color: settings.params.color, 749 distance: settings.params.width, 750 effectId: settings.uniqueId, 751 spread: settings.params.spread, 752 effectsList: ['stroke'] 753 }); 754 } else if (field.settingName === 'text-extrude') { 755 var XYSliderValues = XYSlider.getCurrentValues(); 756 self.drawEffects({ 757 target: self.currentElement, 758 color: settings.params.color, 759 deg: 180 - XYSliderValues.deg * -1, 760 distance: XYSliderValues.distance, 761 effectId: settings.uniqueId, 762 effectsList: ['extrude3d'] 763 }); 764 } else if (field.settingName === 'text-extrude-shadow') { 765 var XYSliderValues = XYSlider.getCurrentValues();
766 self.drawEffects({ 767 color: settings.params.color, 768 target: self.currentElement, 769 deg: 180 - XYSliderValues.deg * -1, 770 distance: XYSliderValues.distance, 771 effectId: settings.uniqueId, 772 effectsList: ['extrude3d', 'shadow3d'] 773 }); 774 } else if (field.settingName === 'text-shadow-multiple') { 775 var XYSliderValues = XYSlider.getCurrentValues(); 776 self.drawEffects({ 777 target: self.currentElement, 778 color: settings.params.color, 779 opacity: settings.params.opacity, 780 deg: 180 - XYSliderValues.deg * -1, 781 distance: XYSliderValues.distance, 782 effectId: settings.uniqueId, 783 effectsList: ['shadow3d'] 784 }); 785 } else { 786 //console.log(field.settingName + ': ' + completeValue); 787 self.updateCssSettings(field.settingName, completeValue); 788 self.updateSelectedElement(field.settingName, completeValue); 789 } 790 return false; 791 }); 792 793 // load defaults 794 if (loadDefaults) { 795 for(var i = 0; i < inputs.length; i++) { 796 inputs.eq(i).trigger('change'); 797 } 798 // 799 inputs.eq(0).trigger('change'); 800 } 801 802 //reset field button action 803 fieldset.find('a.resetField').click(function () { 804 thisInput.val(''); 805 thisInput.trigger('change'); 806 alert('When resetting settings or deleting preset you have to save to see the change'); 807 }); 808 } else { 809 self.settingFields[field.name] = $('<fieldset id="' + field.name + 'Fieldset"><label>' + field.label + '<a class="resetField">reset</a><input type="' + field.type + '" name="' + field.name + '" title="' + field.settingName + '" id="' + field.name + 'Field"></label></fieldset>'); 810 thisField = self.settingFields[field.name]; 811 thisInput = self.getField(field.name); 812 thisInput.data('fieldInfo', field); 813 if (paramObj.target) { 814 paramObj.target.append(thisField); 815 } else if (paramObj.type === 'premium') { 816 self.$extendedFields.append(thisField); 817 } else if (paramObj.type === 'extrafields') { 818 self.modals['extrafields'].append(thisField); 819 } else { 820 if (field.name === 'selector') { 821 thisField.insertAfter('#presetsDropdownFieldset'); 822 } else { 823 self.$standardFields.append(thisField); 824 } 825 } 826 //reset field button action 827 thisField.find('a.resetField').click(function () { 828 thisInput.val(0); 829 thisInput.trigger('change'); 830 thisInput.val('none'); 831 thisInput.trigger('change'); 832 thisInput.val('inherit'); 833 thisInput.trigger('change'); 834 thisInput.val(''); 835 thisInput.trigger('change'); 836 }); 837 if (field.settingType === 'dropdown') { 838 thisInput = self.extendField(thisInput, 'dropdown'); 839 } else { 840 thisInput = self.extendField(thisInput, field.extendWith); 841 } 842 //general actions - apply settings 843 if (field.settingType === 'css' || field.settingType === 'dropdown') { 844 //bind change to color picker 845 thisInput.bind('change click keyup', function () { 846 //console.log($(this).data('fieldInfo').settingName + ', ' + $(this).val() + ', ' + ($(this).data('fieldInfo').unit || '')) 847 self.updateCssSettings($(this).data('fieldInfo').settingName, $(this).val()); 848 self.updateSelectedElement($(this).data('fieldInfo').settingName, $(this).val() + ($(this).data('fieldInfo').unit || '')); 849 return false; 850 }); 851 } else if (field.settingType === 'csstransform') { 852 //bind change to color picker 853 thisInput.bind('change click keyup', function () { 854 //console.log($(this).data('fieldInfo').settingName + ', ' + $(this).val() + ', ' + ($(this).data('fieldInfo').unit || '')) 855 self.updateCssSettings($(this).data('fieldInfo').settingName, $(this).val()); 856 self.updateSelectedElement($(this).data('fieldInfo').settingName, $(this).val() + ($(this).data('fieldInfo').unit || '')); 857 return false; 858 }); 859 } else if (field.settingType === 'general') { 860 //bind change to color picker 861 thisInput.bind('change click', function () { 862 self.updateSettings($(this).data('fieldInfo').settingName, $(this).val()); 863 self.updateSelectedElement($(this).data('fieldInfo').settingName, $(this).val()); 864 return false; 865 }); 866 } 867 } 868 }; 869 // extend field with slider, color picker etc 870 self.extendField = function (field, extendWith) { 871 if (extendWith === 'slider') { 872 var input = (function () { 873 var min = 1, 874 max = 100, 875 step = 1, 876 value = 40, 877 orientation = 'horizontal', 878 reverse = false,
879 $slider = $('<div>'), 880 input = field, 881 fieldset = input.closest('fieldset'); 882 fieldset.addClass('slider-extended'); 883 fieldset.append($slider); 884 if (input.data('fieldInfo').slider) { 885 min = parseFloat(input.data('fieldInfo').slider.min); 886 max = parseFloat(input.data('fieldInfo').slider.max); 887 step = parseFloat(input.data('fieldInfo').slider.step); 888 if (input.data('fieldInfo').slider.orientation) { 889 orientation = input.data('fieldInfo').slider.orientation; 890 } 891 if (input.data('fieldInfo').slider.value) { 892 value = input.data('fieldInfo').slider.value; 893 } 894 if (input.data('fieldInfo').slider.reverse) { 895 reverse = true; 896 } 897 } 898 //init slider 899 $slider.slider({ 900 range: 'min', 901 value: value, 902 min: min, 903 max: max, 904 step: step, 905 orientation: orientation, 906 slide: function (event, ui) { 907 if (!reverse) { 908 input.val(ui.value); 909 } else { 910 //reversed values 911 input.val(max + min - ui.value); 912 } 913 input.trigger('change'); 914 } 915 }); 916 //bind value change to the size slider 917 input.bind('change click', function () { 918 var val = $(this).val(); 919 if (val) { 920 $slider.slider('value', parseFloat(val)); 921 } 922 return false; 923 }); 924 return input; 925 }()); 926 } else if (extendWith === 'dropdown') { 927 var input = (function () { 928 var $dropdown = $('<select><option></option></select>'), 929 input = field, 930 fieldset = input.parents('fieldset'), 931 key; 932 fieldset.addClass('dropdown-extended'); 933 fieldset.find('label').append($dropdown); 934 for(key in input.data('fieldInfo').dropdown) { 935 var val = input.data('fieldInfo').dropdown[key]; 936 $dropdown.append('<option value="' + key + '">' + val + '</option>'); 937 } 938 $dropdown.bind('change', function () { 939 input.val($(this).val()); 940 input.trigger('change'); 941 }); 942 //bind value change to the size slider 943 input.bind('change click', function () { 944 var val = $(this).val(); 945 if (val) { 946 $dropdown.val(val); 947 } 948 return false; 949 }); 950 return input; 951 }()); 952 } else if (extendWith === 'colorPicker') { 953 var input = (function () { 954 var input = field; 955 input.change(function () { 956 $(this).css('backgroundColor', $(this).val()); 957 }); 958 //init color picker 959 input.ColorPicker({ 960 color: '#0000ff', 961 onShow: function (colpkr) { 962 $(colpkr).show(); 963 return false; 964 }, 965 onHide: function (colpkr) { 966 $(colpkr).hide(); 967 return false; 968 }, 969 onChange: function (hsb, hex, rgb) { 970 input.val('#' + hex); 971 input.trigger('change'); 972 input.trigger('change').css('backgroundColor', '#' + hex); 973 }, 974 onBeforeShow: function () { 975 $(this).ColorPickerSetColor(this.value); 976 } 977 }).bind('keyup', function () { 978 $(this).ColorPickerSetColor(this.value); 979 }); 980 return input; 981 }()); 982 } else if (extendWith === 'selectorPicker') { 983 var input = (function (field) { 984 var replacementField, 985 thisInput, 986 selectorPicker, 987 selectorPicker2, 988 input = field, 989 field = field.data('fieldInfo'), 990 fieldset = input.parents('fieldset'); 991 self.settingFields[field.name] = $('<fieldset id="selectorFieldset"><label><input type="' + field.type + '" name="' + field.name + '" title="' + field.settingName + '">CSS selecor editor (advanced)</label></fieldset>'); 992 replacementField = self.settingFields[field.name]; 993 thisInput = self.getField(field.name); 994 selectorPicker = $('<button class="pickElement">Pick element</button>'); 995 selectorPicker2 = $('<button class="pickElement pickAddElement">Pick element(add)</button>'); 996 self.$selectorPicker = selectorPicker; 997 self.$selectorPicker2 = selectorPicker2; 998 // 999 //setTimeout(function () { 1000 self.$selectorPicker.insertBefore(self.settingFields.presets); 1001 //}, 100); 1002 //replacementField.prepend(selectorPicker); 1003 replacementField.prepend(selectorPicker2); 1004 selectorPicker.on('click', function () { 1005 self.bindGetSelector(); 1006 return false; 1007 }); 1008 selectorPicker2.on('click', function () { 1009 self.bindGetSelector(true); 1010 return false; 1011 }); 1012 //replace default field 1013 fieldset.replaceWith(replacementField); 1014 replacementField.find('label').hide(); 1015 thisInput.data('fieldInfo', field); 1016 //return replaced input 1017 return thisInput; 1018 }(field)); 1019 } 1020 return input; 1021 }; 1022 // get field value 1023 self.getField = function (name) { 1024 var input = self.settingFields[name].find('input'); 1025 return input; 1026 }; 1027 // set field value 1028 self.setField = function (name, value) { 1029 var input = self.getField(name); 1030 input.val(value); 1031 input.trigger('change'); 1032 }; 1033 /* 1034 * EFFECTS 1035 */ 1036 self.loadEffectsPanel = function (data) { 1037 var i, 1038 field, 1039 paramObj, 1040 dropdown, 1041 option, 1042 field, 1043 effectsList = $('<div class="effectsList">'); 1044 // save effects to array 1045 self.effects = data; 1046 // Create effects modal 1047 var modalOptions = { 1048 id: 'effectsPanel', 1049 name: 'effects', // name conflict was here 1050 title: 'Effects', 1051 left: '50%', 1052 top: '50px', 1053 width: '190px' 1054 }; 1055 var modal = self.createNewModal(modalOptions); 1056 dropdown = $('<select>'); 1057 dropdown.append($('<option>Add new effect</option>')); 1058 // add options to the modal 1059 for (i = 0; i < data.length; i += 1) { 1060 field = data[i]; 1061 option = $('<option value="' + field.settingName + '">' + field.label + '</option>'); 1062 dropdown.append(option); 1063 } 1064 if (data.length < 3) { 1065 dropdown.append('<option value="upgrade">More options</option>'); 1066 } 1067 // add dropdown to modal 1068 modal.append(dropdown); 1069 // change 1070 dropdown.change(function () { 1071 if ($(this).val() == 'upgrade') { 1072 var link = $('<a href="http://fontsforweb.com/purchase/pluginupgradesubscribe?url=' + fontBlogUrl + '&name=' + fontBlogName + '" class="overlay_url" id="upgradeToProButton" data-upgrade="true">Pro settings</a>').appendTo('body'); 1073 link.click(); 1074 link.remove(); 1075 return; 1076 } 1077 self.addEffect($(this).val()); 1078 dropdown.find('option').eq(0).attr('selected', 'selected'); 1079 }); 1080 modal.append(effectsList); 1081 effectsList.sortable({ 1082 stop: function () { 1083 // get new order of items 1084 var items = effectsList.find('> div'), 1085 newEffectsOrder = []; 1086 // for each item 1087 items.each(function (ind) { 1088 var effectSettings = $(this).data('settings'); 1089 effectSettings.effectNo = ind; 1090 newEffectsOrder.push(effectSettings); 1091 }); 1092 self.currentPreset.effects = newEffectsOrder; 1093 // refresh text shadow effects 1094 self.updateTextShadowEffects(self.currentElement); 1095 } 1096 }); 1097 }; 1098 /* 1099 * Styles 1100 */ 1101 self.loadStylesPanel = function (data) { 1102 var i, 1103 field, 1104 paramObj, 1105 $list, 1106 field, 1107 $li, 1108 $div; 1109 // save effects to array 1110 self.styles = data; 1111 // Create styles modal 1112 var modalOptions = { 1113 id: 'stylesPanel', 1114 name: 'styles', // name conflict was here 1115 title: 'Style presets', 1116 right: '0', 1117 top: '50px', 1118 width: '400px' 1119 }; 1120 var modal = self.createNewModal(modalOptions); 1121 $list = $('<ul>'); 1122 // add dropdown to modal 1123 modal.append($list); 1124 // add options to the modal 1125 for (i = 0; i < data.length; i += 1) { 1126 field = data[i];
1127 $div = $('<div>'); 1128 $li = $('<li>').append($div) 1129 $list.append($li); 1130 1131 $div.text(field.label); 1132 $div.attr('data-value', field.settingName); 1133 1134 // create temporary preset 1135 self.createPreset(field.settingName, '[data-value="' + field.settingName + '"]'); 1136 self.loadStylePreset(field.settingName); 1137 self.unhighlightCurrent(); 1138 self.deletePreset(self.currentPresetNo, true); 1139 } 1140 if (data.length < 3) { 1141 var button = $('<button>More options</button>'); 1142 $list.append(button); 1143 button.click(function () { 1144 var link = $('<a href="http://fontsforweb.com/purchase/pluginupgradesubscribe?url=' + fontBlogUrl + '&name=' + fontBlogName + '" class="overlay_url" id="upgradeToProButton" data-upgrade="true">Pro settings</a>').appendTo('body'); 1145 link.click(); 1146 link.remove(); 1147 return; 1148 }); 1149 } 1150 modal.append(button); 1151 // change 1152 $list.on('click', 'li', function () { 1153 var value = $(this).find('div').data('value'); 1154 if (value === 'upgrade') { 1155 var link = $('<a href="http://fontsforweb.com/purchase/pluginupgradesubscribe?url=' + fontBlogUrl + '&name=' + fontBlogName + '" class="overlay_url" id="upgradeToProButton" data-upgrade="true">Pro settings</a>').appendTo('body'); 1156 link.click(); 1157 link.remove(); 1158 return; 1159 } else if (!value) { 1160 return; 1161 } 1162 self.loadStylePreset(value); 1163 }); 1164 }; 1165 /** 1166 * Load style from style presets 1167 **/ 1168 self.loadStylePreset = function (settingName) { 1169 var stylePreset = self.getStyleDefinitionByName(settingName), 1170 presetSettings = stylePreset.presetSettings; 1171 1172 self.unloadCurrentElementEffects(); 1173 self.currentPreset.effects = []; 1174 1175 self.populateStyles(presetSettings); 1176 1177 $.extend(true, self.currentPreset, presetSettings); 1178 self.loadEffectSettings(); 1179 self.applyFont(); 1180 self.loadFontPreview(); 1181 }; 1182 /* 1183 * load effect settings 1184 */ 1185 self.loadEffectSettings = function () { 1186 // if no effects loaded yet quit 1187 if (!self.effects) return; 1188 if (!self.currentPreset.effects) return; 1189 1190 // get effect saved settings 1191 for (var i = 0; i < self.currentPreset.effects.length; i++) { 1192 var effect = self.currentPreset.effects[i], 1193 // add effect in order to the effects list 1194 $effectItem = self.createEffectEntry(effect); 1195 if (effect.enabled) { 1196 $effectItem.find('input[name=enabled]').attr("checked", "true"); 1197 } 1198 // go through all the parameters and set them accordingly 1199 // clone object beforehand to avoid properties overwriting inside effect 1200 var params = $.extend(true, {}, effect.params); 1201 for (var property in params) { 1202 var value = params[property]; 1203 // get field from current effect 1204 var found = $effectItem.find('input[title=' + property + ']'); 1205 if (found.length) { 1206 found.val(value); 1207 found.trigger('change'); 1208 } 1209 } 1210 } 1211 }; 1212 /* 1213 * Unload current effect 1214 * 1215 * @returns {unresolved} 1216 */ 1217 self.unloadCurrentElementEffects = function () { 1218 //console.log(self.effectSliders, self.currentPreset, self.currentPreset.effects); 1219 if (self.currentPreset === undefined || self.currentPreset.effects === undefined) return; 1220 if (self.effectSliders && Object.size(self.effectSliders)) { 1221 // unload all handles 1222 for (var i = 0; i < self.currentPreset.effects.length; i++) { 1223 var effect = self.currentPreset.effects[i]; 1224 if (self.effectSliders[effect.uniqueId]) { 1225 self.effectSliders[effect.uniqueId].hide(); 1226 } 1227 } 1228 } 1229 1230 if (!self.modals['effects']) return; 1231 self.modals['effects'].find('.effectsList').html(''); 1232 }; 1233 /* 1234 * add effect to effects list 1235 */ 1236 self.addEffect = function (settingName) { 1237 var effectSettings = {}, 1238 loadDefaults = 1; 1239 if (!self.currentPreset.effects) { 1240 self.currentPreset.effects = []; 1241 effectSettings.effectNo = 0; 1242 } else { 1243 effectSettings.effectNo = self.currentPreset.effects.length; 1244 } 1245 effectSettings.settingName = settingName; 1246 effectSettings.uniqueId = effectSettings.effectNo + Math.round(Math.random() * 1000000000) + settingName; 1247 effectSettings.enabled = 1; 1248 // add effect settings to preset 1249 self.currentPreset.effects.splice(0, 0, effectSettings); 1250 // create entry
1251 return self.createEffectEntry(effectSettings, loadDefaults); 1252 }; 1253 /* 1254 * add effect to the list 1255 * 1256 * @param {type} effectId 1257 * @returns {effect} 1258 */ 1259 self.createEffectEntry = function (effectSettings, loadDefaults) { 1260 //if effects modal not created yet don't load effects 1261 if (!self.modals['effects']) return; 1262 var effectItem, 1263 effectDefinition = self.getEffectDefinitionByName(effectSettings.settingName), 1264 effectsModal = self.modals['effects'].find('.effectsList'), 1265 effectParams = $('<div class="params"></div>'), 1266 enabledCheckbox = $('<input type="checkbox" name="enabled">'), 1267 arrow = $('<a href="#" class="effectArrow"></a>'), 1268 label = $('<a href="#" class="effectName">' + effectDefinition.label + '</a>'), 1269 closeButton = $('<a href="#" class="removeEffect">x</a>'); 1270 if (loadDefaults === undefined) { 1271 loadDefaults = 0; 1272 } 1273 // create item markup 1274 effectItem = $('<div>'); 1275 effectItem.append('<div class="label">'); 1276 effectItem.find('.label').append(arrow); 1277 effectItem.find('.label').append(enabledCheckbox); 1278 effectItem.find('.label').append(label); 1279 effectItem.find('.label').append(closeButton); 1280 effectItem.append(effectParams); 1281 effectParams.hide(); 1282 if (effectSettings.enabled) { 1283 enabledCheckbox.attr('checked', 'true'); 1284 } 1285 // add settings 1286 effectsModal.prepend(effectItem); 1287 var paramObj = []; 1288 paramObj.field = effectDefinition; 1289 paramObj.settings = effectSettings; 1290 paramObj.target = effectParams; 1291 paramObj.type = 'extrafields'; 1292 1293 // actions 1294 label.click(function (e) { 1295 if (effectParams.is(':visible')) { 1296 arrow.animateRotate(0); 1297 } else { 1298 arrow.animateRotate(90); 1299 } 1300 e.preventDefault(); 1301 effectParams.slideToggle(); 1302 }); 1303 arrow.click(function (e) { 1304 if (effectParams.is(':visible')) { 1305 arrow.animateRotate(0); 1306 } else { 1307 arrow.animateRotate(90); 1308 } 1309 e.preventDefault(); 1310 effectParams.slideToggle(); 1311 }); 1312 // close button 1313 closeButton.click(function (e) { 1314 e.preventDefault(); 1315 // delete effect from 1316 self.removeEffect(effectSettings.uniqueId, effectItem); 1317 }); 1318 // enable disable checkbox 1319 enabledCheckbox.click(function (e) { 1320 if ($(this).is(':checked')) { 1321 self.enableEffect(effectSettings.uniqueId, effectItem); 1322 } else { 1323 self.disableEffect(effectSettings.uniqueId, effectItem); 1324 } 1325 }); 1326 self.addSettingsField(paramObj, loadDefaults); 1327 //add item reference in settings and settings in item 1328 //effectSettings.el = effectItem; ERROR on stringify 1329 effectItem.data('settings', effectSettings); 1330 return effectItem; 1331 }; 1332 /* 1333 * get effect definition by id 1334 */ 1335 self.getEffectDefinitionByName = function (effectId) { 1336 if (!self.effects) return false; 1337 // go thorugh all effects and find the ONE 1338 for (var i = 0; i < self.effects.length; i++) { 1339 var effect = self.effects[i]; 1340 if (effect.settingName === effectId) { 1341 return effect; 1342 } 1343 } 1344 return false; 1345 }; 1346 /* 1347 * get style 1348 */ 1349 self.getStyleDefinitionByName = function (styleId) { 1350 if (!self.styles) return false; 1351 // go thorugh all effects and find the ONE 1352 for (var i = 0; i < self.styles.length; i++) { 1353 var style = self.styles[i]; 1354 if (style.settingName === styleId) { 1355 return style; 1356 } 1357 } 1358 return false; 1359 }; 1360 /* 1361 * Enable effect 1362 * 1363 * @param {type} effectId 1364 */ 1365 self.enableEffect = function (effectId, $effectItem) { 1366 if (!self.currentPreset.effects) return false; 1367 var effect = self.getElementsEffect(effectId); 1368 effect.enabled = 1; 1369 // if has handle show it 1370 if (self.effectSliders[effectId]) { 1371 self.effectSliders[effectId].show(); 1372 } 1373 // update text shadow effects 1374 self.updateTextShadowEffects(self.currentElement); 1375 }; 1376 /* 1377 * Disable effect 1378 * 1379 * @param {type} effectId 1380 */ 1381 self.disableEffect = function (effectId, $effectItem) { 1382 if (!self.currentPreset.effects) return false; 1383 var effect = self.getElementsEffect(effectId); 1384 effect.enabled = 0; 1385 // delete shadow css 1386 self.removeShadowEffect(effectId); 1387 // if has handle hide it 1388 if (self.effectSliders[effectId]) { 1389 self.effectSliders[effectId].hide(); 1390 } 1391 }; 1392 /* 1393 * Delete effect from an element 1394 * 1395 * @param {type} effectId 1396 */ 1397 self.removeEffect = function (effectId, $effectItem) { 1398 if (!confirm('Remove the effect?')) return; 1399 if (!self.currentPreset.effects) return false; 1400 // go thorugh all effects and find the ONE 1401 for (var i = 0; i < self.currentPreset.effects.length; i++) { 1402 var effect = self.currentPreset.effects[i]; 1403 if (effect.uniqueId === effectId) { 1404 self.currentPreset.effects.splice(i, 1); 1405 } 1406 } 1407 // delete shadow css 1408 self.removeShadowEffect(effectId); 1409 if (self.effectSliders[effectId]) { 1410 // remove handle 1411 self.effectSliders[effectId].remove(); 1412 } 1413 // delete entry 1414 $effectItem.remove(); 1415 }; 1416 /* 1417 * Get effect of an element 1418 * 1419 * @param {type} effectId 1420 */ 1421 self.getElementsEffect = function (effectId) { 1422 if (!self.currentPreset.effects) return false; 1423 // go thorugh all effects and find the ONE 1424 for (var i = 0; i < self.currentPreset.effects.length; i++) { 1425 var effect = self.currentPreset.effects[i]; 1426 if (effect.uniqueId === effectId) { 1427 return effect; 1428 } 1429 } 1430 }; 1431 /* 1432 draw effects 1433 options.target; 1434 options.deg; 1435 options.distance; 1436 options.effectId; 1437 options.effectsList; 1438 */ 1439 self.drawEffects = function (options) { 1440 if (!self.shadowSupport) return false; 1441 var depth = options.distance / 10, 1442 subjectColor = options.target.css('color'), 1443 color = options.color, 1444 subjectColorRgb = self.parseRgb(subjectColor), 1445 rColor = subjectColorRgb.r, 1446 gColor = subjectColorRgb.g, 1447 bColor = subjectColorRgb.b, 1448 i = 0, 1449 j = 0, 1450 speed = i, 1451 xDist = 0, 1452 yDist = 0, 1453 //get effect 1454 effect = self.getElementsEffect(options.effectId), 1455 angle = options.deg; 1456 if (color) { 1457 var colorRgb = self.html2rgb(color.replace('#', '')); 1458 } else { 1459 colorRgb = subjectColorRgb; 1460 } 1461 // set default angle 1462 if (angle === undefined) { 1463 angle = 290; 1464 } 1465 // reset current elements calculated effect value 1466 effect.calculated = ''; 1467 // go through effects which should be applied 1468 for (i = 0; i < options.effectsList.length; i++) { 1469 depth = options.distance / 10; 1470 var effectName = options.effectsList[i]; 1471 switch (effectName) { 1472 case 'textShadow': 1473 effect.calculated += options.completeValue; 1474 //console.log(effect.calculated); 1475 //completeValue += ' ' + $(this).val() + unit; 1476 //effect.calculated = completeValue.replace(/, +$/,'') 1477 break; 1478 case 'stroke': 1479 var spread = 2; 1480 if (options.spread) { 1481 spread = options.spread; 1482 } 1483 // if distance is bigger than 4 add 1484 if (options.distance > 4) { 1485 // slash 1486 effect.calculated += options.distance + 'px ' + options.distance + 'px ' + spread + 'px ' + color + ', '; 1487 effect.calculated += -options.distance + 'px ' + options.distance + 'px ' + spread + 'px ' + color + ', '; 1488 effect.calculated += options.distance + 'px ' + -options.distance + 'px ' + spread + 'px ' + color + ', '; 1489 effect.calculated += -options.distance + 'px ' + -options.distance + 'px ' + spread + 'px ' + color + ', '; 1490 // top and down 1491 effect.calculated += options.distance + 'px 0px ' + spread + 'px ' + color + ', '; 1492 effect.calculated += -options.distance + 'px 0px ' + spread + 'px ' + color + ', '; 1493 effect.calculated += '0px ' + options.distance + 'px ' + spread + 'px ' + color + ', '; 1494 effect.calculated += '0px ' + -options.distance + 'px ' + spread + 'px ' + color + ', '; 1495 } else { 1496 // only slash 1497 effect.calculated += options.distance + 'px ' + options.distance + 'px ' + spread + 'px ' + color + ', '; 1498 effect.calculated += -options.distance + 'px ' + options.distance + 'px ' + spread + 'px ' + color + ', '; 1499 effect.calculated += options.distance + 'px ' + -options.distance + 'px ' + spread + 'px ' + color + ', '; 1500 effect.calculated += -options.distance + 'px ' + -options.distance + 'px ' + spread + 'px ' + color + ', '; 1501 } 1502 case 'extrude3d': 1503 // get color color 1504 rColor = colorRgb.r; 1505 gColor = colorRgb.g; 1506 bColor = colorRgb.b; 1507 //initially take 20% off
1508 rColor = rColor / 100 * 80, 1509 gColor = gColor / 100 * 80, 1510 bColor = bColor / 100 * 80; 1511 //loop to depth 1512 for (j = 0; j < depth; j++) { 1513 //calculate x and y of next shadow 1514 speed = 1.2; 1515 xDist += speed * Math.sin(angle * Math.PI / 180); 1516 yDist += speed * -Math.cos(angle * Math.PI / 180); 1517 xDist = xDist; 1518 yDist = yDist; 1519 //percentage darkened 1520 var percentageDone = j / depth; 1521 //darkening strength - the bigger depth the lower sstrength 1522 var light = 10 - percentageDone * 10; 1523 //darken the next shadow a bit take 10% 1524 rColor = Math.floor(rColor / 100 * 91 + light); 1525 gColor = Math.floor(gColor / 100 * 91 + light); 1526 bColor = Math.floor(bColor / 100 * 91 + light); 1527 color = 'rgb(' + rColor + ', ' + gColor + ', ' + bColor + ')'; 1528 //put together shadow setting 1529 effect.calculated += xDist.toFixed(2) + 'px ' + yDist.toFixed(2) + 'px ' + 0.3 + 'px ' + color + ', '; 1530 } 1531 break; 1532 case 'shadow3d': //generate text shadow value 1533 // get color color 1534 rColor = colorRgb.r; 1535 gColor = colorRgb.g; 1536 bColor = colorRgb.b; 1537 //loop to depth 1538 for (j = 0; j < depth; j++) { 1539 if (j > 3 && i % 3) continue; 1540 //calculate x and y of next shadow 1541 speed = 6; 1542 xDist += speed * Math.sin(angle * Math.PI / 180); 1543 yDist += speed * -Math.cos(angle * Math.PI / 180); 1544 xDist = xDist; 1545 yDist = yDist; 1546 //lighten the next shadow a bit take 10% 1547 rColor = Math.floor(rColor / 90 * 100); 1548 gColor = Math.floor(gColor / 90 * 100); 1549 bColor = Math.floor(bColor / 90 * 100); 1550 var opacity = options.opacity; 1551 if (!opacity) opacity = 0.3; 1552 color = 'rgba(' + rColor + ', ' + gColor + ', ' + bColor + ', ' + opacity + ')'; 1553 //put together shadow setting 1554 effect.calculated += xDist.toFixed(2) + 'px ' + yDist.toFixed(2) + 'px ' + ((j + 1) * 2) + 'px ' + color + ', '; 1555 } 1556 break; 1557 } 1558 } 1559 // filter result 1560 effect.calculated = effect.calculated.replace(/, +$/, ''); 1561 //apply text shadow 1562 self.updateTextShadowEffects(options.target); 1563 }; 1564 /* 1565 * Remove shadow effect 1566 * 1567 * @param {type} subject 1568 */ 1569 self.removeShadowEffect = function (effectId) { 1570 // delete from shadow effects 1571 delete self.currentPreset.shadowEffects[effectId]; 1572 // update shadow effects on given element 1573 self.updateTextShadowEffects(self.currentElement); 1574 }; 1575 //update effects 1576 self.updateTextShadowEffects = function (subject) { 1577 var allShadows = ''; 1578 // go through all currently applied 1579 for (var i = 0; i < self.currentPreset.effects.length; i++) { 1580 var effect = self.currentPreset.effects[i]; 1581 if (effect.calculated && effect.enabled) { 1582 if (allShadows) allShadows += ', '; 1583 allShadows += effect.calculated; 1584 } 1585 } 1586 if (allShadows === '') { 1587 allShadows = 'none'; 1588 } 1589 //get all different text shadows 1590 //subject[0].style.textShadow = allShadows + ' !important'; 1591 subject.each(function () { 1592 $(this).style('textShadow', allShadows, 'important'); 1593 }); 1594 self.updateCssSettings('text-shadow', allShadows); 1595 }; 1596 /* 1597 * 1598 * PRESETS MANAGEMENT 1599 * 1600 */ 1601 /* 1602 * 1603 * Create a new preset - selection 1604 * 1605 */ 1606 self.createPreset = function (presetName, selector) { 1607 var property, 1608 newPreset, 1609 newPresetId; 1610 if (selector === undefined || !selector) { 1611 selector = 'PICK AN ELEMENT NOW - or type CSS selector(advanced)'; 1612 } 1613 //get first preset as a template 1614 newPreset = {}; 1615 //set preset variables 1616 newPreset.name = presetName; 1617 newPreset.selector = selector; 1618 newPreset.fontid = ''; 1619 newPreset.fontName = ''; 1620 newPreset.effects = []; 1621 // !!! when styles are array they are not visible for PHP? 1622 newPreset.styles = {}; 1623 //reset css styles 1624 for (property in newPreset.styles) { 1625 newPreset.styles[property] = ''; 1626 } 1627 //push the preset at the end 1628 newPresetId = self.options.presets.push(newPreset) - 1; 1629 //add preset to the dropdown and select it 1630 self.$presetsDropdown.append('<option value="' + newPresetId + '">' + presetName + '</option>'); 1631 //get preset id and load it 1632 self.loadPreset(newPresetId); 1633 }; 1634 //add new preset 1635 self.renamePreset = function () { 1636 //current preset option 1637 var currPresetOption = self.$presetsDropdown.find('option[value=' + self.currentPresetNo + ']'), 1638 presetName = prompt('New preset name i.e. paragraph', currPresetOption.text()), 1639 property; 1640 if (!presetName) { 1641 return; 1642 } 1643 self.$presetsDropdown.find('option[value=' + self.currentPresetNo + ']').text(presetName); 1644 self.currentPreset.name = presetName; 1645 }; 1646 //delete preset 1647 self.deletePreset = function (presetNo, silent) { 1648 if(silent === undefined) { 1649 if (!confirm("Are you sure you want to delete this preset?")) { 1650 return false; 1651 } 1652 } 1653 if (self.options.presets.length === 1) { 1654 alert('At least one preset has to be present'); 1655 return; 1656 } 1657 if(silent === undefined) { 1658 self.unhighlightCurrent(); 1659 } 1660 self.options.presets.splice(presetNo, 1); 1661 self.$presetsDropdown.find('option[value=' + presetNo + ']').remove(); 1662 // delete all presets 1663 self.$presetsDropdown.html(''); 1664 // recreate presets menu to number values from 0 1665 for (var i = 0; i < self.options.presets.length; i += 1) { 1666 var preset = self.options.presets[i], 1667 presetName = self.options.presets[i].name, 1668 presetId = i; 1669 // unwire all outlined elements 1670 if (preset.selector.indexOf('ELEMENT NOW') === -1 && preset.selector.indexOf('PICK ELEMENT') === -1) { 1671 $(preset.selector).data('wired', false); 1672 } 1673 self.$presetsDropdown.append('<option value="' + presetId + '">' + presetName + '</option>'); 1674 } 1675 if(silent === undefined) { 1676 self.outlineAllPresets(); 1677 alert('When resetting settings or deleting preset you have to save to see the change'); 1678 self.loadPreset(0); 1679 } else if (self.options.presets && self.options.presets[1]) { 1680 self.loadPreset(1); 1681 } else { 1682 self.loadPreset(0); 1683 } 1684 }; 1685 //delete current preset 1686 self.deleteCurrentPreset = function () { 1687 self.deletePreset(self.currentPresetNo); 1688 }; 1689 /* 1690 * Reload currently loaded preset 1691 */ 1692 self.reloadPreset = function () { 1693 self.loadPreset(self.currentPresetNo); 1694 }; 1695 /* 1696 * load preset - load selection with all param values 1697 * 1698 * @param {type} presetNo 1699 * @returns {unresolved} 1700 */ 1701 self.loadPreset = function (presetNo) { 1702 var preset; 1703 presetNo = parseInt(presetNo, 10); 1704 var preset = self.options.presets[presetNo]; 1705 1706 self.unloadPreset(); 1707 if (!preset) { 1708 return; 1709 } 1710 if (self.mode === 'postPage') return; 1711 // if this is preset 0 hide appearance panel 1712 if (presetNo === 0) { 1713 self.$apr.hide(); 1714 } else { 1715 self.$apr.show(); 1716 } 1717 // if only one preset exists hide appearance panel 1718 if (self.options.presets.length == 1) { 1719 self.settingFields.presets.hide(); 1720 self.$selectorPicker2.hide(); 1721 } else { 1722 self.settingFields.presets.show(); 1723 self.$selectorPicker2.show(); 1724 } 1725 // unload effects 1726 self.unloadCurrentElementEffects(); 1727 self.currentPresetNo = presetNo; 1728 self.currentPreset = preset;
1729 // if current selector is invalid current element is false 1730 if (self.currentPreset.selector.indexOf('ELEMENT NOW') !== -1 || self.currentPreset.selector.indexOf('PICK ELEMENT') !== -1) { 1731 self.currentElement = false; 1732 } else { 1733 // otherwise get current element 1734 self.currentElement = $(self.currentPreset.selector); 1735 } 1736 // add space for shadow effects 1737 self.currentPreset.shadowEffects = []; 1738 //select preset from dropdown 1739 self.$presetsDropdown.val(presetNo); 1740 self.populateStyles(preset); 1741 self.highlightCurrent(); 1742 //load effects 1743 self.loadEffectSettings(); 1744 self.loadFontPreview(); 1745 }; 1746 self.populateStyles = function (preset) { 1747 var property, 1748 found; 1749 /* 1750 populate general fields 1751 */ 1752 for (property in preset) { 1753 found = $('body').find('input[title=' + property + ']'); 1754 if (found.length) { 1755 found.val(preset[property]); 1756 found.trigger('change'); 1757 } 1758 } 1759 /* 1760 populate css fields 1761 */ 1762 for (property in preset.styles) { 1763 found = $('body').find('input[title=' + property + ']'); 1764 if (found.length) { 1765 found.val(preset.styles[property]); 1766 found.trigger('change'); 1767 } 1768 } 1769 }; 1770 self.unloadPreset = function () { 1771 var $field, 1772 $input, 1773 $dropdown, 1774 key; 1775 // go through all fields 1776 for (key in self.settingFields) { 1777 $dropdown = []; 1778 $field = self.settingFields[key]; 1779 if (!$field || !($field instanceof $)) { 1780 continue; 1781 } 1782 $input = $field.find('input'); 1783 $input.val(''); 1784 //$input.trigger('change'); 1785 $dropdown = $field.find('select'); 1786 if ($dropdown.length) { 1787 $dropdown.val(''); 1788 $input.hide(); 1789 } 1790 } 1791 }; 1792 self.loadFontPreview = function () { 1793 var preset = self.currentPreset, 1794 imageUrl = '', 1795 originalBg = $('#fontfaceSettings').data('originalBackground'); 1796 if (preset['fontid'] && preset['fontName']) { 1797 if (!originalBg) { 1798 $('#fontfaceSettings').data('originalBackground', $('#fontfaceSettings').css('backgroundImage')); 1799 } 1800 imageUrl = self.options.FFW_baseUrl + '/public/fonts/' + preset['fontid'] + '/' + preset['fontName'] + '.png'; 1801 $('#fontfaceSettings').css({'backgroundImage': 'url(' + imageUrl + ')'}); 1802 } else if (originalBg) { 1803 $('#fontfaceSettings').css({'backgroundImage': $('#fontfaceSettings').data('originalBackground')}); 1804 } 1805 } 1806 /** 1807 * 1808 * FONTS BROWSER 1809 * 1810 */ 1811 /* 1812 Create HTML markup 1813 */ 1814 self.createFontPanel = function () { 1815 var i; 1816 var iframe = '<iframe style="width:98%; height:200px; border:none; margin: 10px 1%" frameBorder="0" src="http://fontsforweb.com/user/pluginactivate?apikey=' + self.options.apikey + '&blogurl=' + fontBlogUrl + '"></iframe>'; 1817 1818 //create html within font browser 1819 self.$el.show(); 1820 self.$el.append($('<h1 class="draggableModalBar"><a class="closeModal" href="#">x</a></h1>')); 1821 self.$el.append('<div class="tablinks"><a class="tablink" href="fontslist">Fontsforweb.com</a><a class="tablink" href="uploaded">Upload</a><a class="tablink" href="pro">PRO settings</a></div>'); 1822 self.$el.append('<div class="tab" id="fontslist"></div>'); 1823 self.$el.append('<div class="tab" id="uploaded"><div class="loading"></div></div>'); 1824 self.$el.append('<div class="tab" id="pro">' + iframe + '</div>'); 1825 1826 self.$el.find('.tab').hide(); 1827 self.$el.find('.tab').eq(0).show(); 1828 self.$el.find('.tablink').on('click', function (e) { 1829 var target, 1830 tab; 1831 e.preventDefault(); 1832 self.$el.find('.tab').hide(); 1833 target = $(this).attr('href'); 1834 tab = self.$el.find('#' + target).show(); 1835 if (target === 'uploaded') { 1836 self.loadPrivateFonts(); 1837 } 1838 return false; 1839 }); 1840 self.$el.css('left', '0') 1841 .draggable({ 1842 handle: self.$el.find('.draggableModalBar') 1843 }); 1844 $('body').on('mousedown', '.draggableModal', function () { 1845 self.modalToTop(this); 1846 }); 1847 self.$el.find('a.closeModal').on('click', function () { 1848 self.$el.hide(); 1849 return false; 1850 }); 1851 }; 1852 /* 1853 * Show fonts browser 1854 */ 1855 self.showFontsBrowser = function () { 1856 if (!this.fontInitialized) { 1857 self.createFontPanel(); 1858 self.loadFontCategories(); 1859 this.fontInitialized = true; 1860 } else {
1861 self.$el.toggle(); 1862 } 1863 self.modalToTop(self.$el); 1864 }; 1865 /* 1866 * Init fonts browser carousel 1867 */ 1868 self.initCarousel = function () { 1869 var carousel = self.$el.find('#FFW_browser_carousel').fcarousel({ 1870 buttonNextHTML: '<a href="#" onclick="return false;"></a>', 1871 buttonPrevHTML: '<a href="#" onclick="return false;"></a>', 1872 animation: 1000, 1873 scroll: 2 1874 }); 1875 }; 1876 /* 1877 * Load font categories 1878 */ 1879 self.loadFontCategories = function () { 1880 //make ajax request to get categories 1881 self.xhrPost({ 1882 url: self.options.FFW_baseUrl + '/fontcategories/fontplugininit', 1883 data: { 1884 apikey: self.options.apikey, 1885 blogurl: fontBlogUrl, 1886 ver: self.version 1887 }, 1888 format: 'html' 1889 }, 1890 function (data) { 1891 //if empty answer display error 1892 if (!data || data === '') { 1893 self.$el.html('<h1>An error has occurde</h1><p>Please try again later</p>'); 1894 } 1895 //hide loader 1896 self.$el.find('#loading').remove(); 1897 //show fonts list 1898 self.$el.find('#fontslist').html(data); 1899 //bind close to close button 1900 self.$el.find('a.close_link').on('click', function () { 1901 self.$el.toggle(); 1902 }); 1903 //init carousel 1904 self.initCarousel(); 1905 }); 1906 }; 1907 /* 1908 * bind onclick to links to reveal subcategories 1909 */ 1910 self.bindShowCategoriesAction = function () { 1911 $('body').on('click', self.baseSelector + ' #categoriesList > ul li a.categoryChoose', function () { 1912 var categoryId = $(this).attr('name'); 1913 //hide all subcategories of other parents 1914 self.$el.find('#subcategoriesList li').hide(); 1915 self.$el.find('#subcategoriesList li.instructions').show(); 1916 //show all subcategories of this parent 1917 self.$el.find('#subcategoriesList li#FFW_parentcategory_' + categoryId).show(); 1918 self.$el.find('.fcarousel-next').click(); 1919 return false; 1920 }); 1921 }; 1922 //bind onclick to reveal font of category 1923 self.bindShowFontsAction = function () { 1924 //bind onclick subcategories to load their fonts 1925 $('body').on('click', self.baseSelector + ' #subcategoriesList > ul li a.categoryChoose', function () { 1926 var categoryId = $(this).attr('name'); 1927 self.xhrPost({ 1928 url: self.options.FFW_baseUrl + '/fontcategories/wpfontsforwebcategoryfonts/catid/' + categoryId, 1929 data: { 1930 apikey: self.options.apikey, 1931 blogurl: fontBlogUrl 1932 }, 1933 format: 'html' 1934 }, 1935 function (data) { 1936 //if empty answer display error 1937 if (!data || data === '') { 1938 self.$el.html('<h1>An error has occurde</h1><p>Please reload page and try again later</p>'); 1939 } 1940 //apply content to div 1941 self.$el.find('#fontList').html(data); 1942 //move carousel right 1943 self.$el.find('.fcarousel-next').click(); 1944 }); 1945 return false; 1946 }); 1947 //bind delete function 1948 $('body').on('click', self.baseSelector + ' #uploaded a.delete', function () { 1949 if (!confirm("Are you sure you want to delete this font?")) { 1950 return false; 1951 } 1952 var fontId = $(this).attr('name'); 1953 self.xhrPost({ 1954 url: self.options.FFW_baseUrl + '/api', 1955 data: { 1956 action: 'deletefont', 1957 apikey: self.options.apikey, 1958 blogurl: fontBlogUrl, 1959 fontid: fontId 1960 } 1961 }, function (data) { 1962 if (data.success === 'true') { 1963 self.loadPrivateFonts(); 1964 } else { 1965 alert('Font deleting error.'); 1966 $('.fontUploadForm').show(); 1967 $('.fontUploading').hide(); 1968 } 1969 }); 1970 return false; 1971 }); 1972 }; 1973 /* 1974 * when clicked on font in fonts browser 1975 */ 1976 self.setFontOnclick = function () { 1977 var selector;
1978 //bind onclick font change action to font images 1979 $('body').on('click', self.baseSelector + ' #fontList a.font_pick, ' + self.baseSelector + ' .fontsList a.font_pick', function () { 1980 var element, 1981 fontName = $(this).parent().attr('title'), 1982 selector; 1983 //PAGE POST version 1984 if (self.mode === 'postPage') { //it's single post editing page 1985 //set font to id from name attribute of a 1986 self.setTinyMCEFont($(this).attr('name'), fontName); 1987 return false; 1988 } else { //GENERAL VERSION 1989 //get selector 1990 selector = self.currentPreset.selector; 1991 //exit when default selector 1992 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 1993 return; 1994 } 1995 //set form fields 1996 self.currentPreset.fontid = $(this).attr('name'); 1997 self.currentPreset.fontName = fontName; 1998 //get target element from iframe or current page 1999 if ($("#header1preview").length) { 2000 element = $("#header1preview").contents().find(); 2001 self.applyFont(element); 2002 } else { 2003 self.applyFont(); 2004 } 2005 self.loadFontPreview(); 2006 return false; 2007 } 2008 }); 2009 }; 2010 /** 2011 * apply font to selection 2012 **/ 2013 self.applyFont = function (frame) { 2014 //get selector 2015 var element, 2016 elements, 2017 fontName = self.currentPreset.fontName, 2018 selector = self.currentPreset.selector, 2019 head, 2020 linkElement; 2021 2022 if(frame === undefined) { 2023 element = $(document); 2024 head = document.getElementsByTagName('head')[0]; 2025 } else { 2026 element = frame; 2027 head = element[0].getElementsByTagName('head')[0]; 2028 } 2029 2030 linkElement = $(document.createElement('link')); 2031 //get and add stylesheet 2032 linkElement.attr({ 2033 href: self.options.FFW_baseUrl + '/font/generatepreviewcss/?id=' + self.currentPreset.fontid, 2034 rel: 'stylesheet', 2035 type: 'text/css' 2036 }); 2037 linkElement.appendTo(head); 2038 //set font family to a selector 2039 elements = element.find(selector); 2040 elements.each(function () { 2041 $(this).style("font-family", fontName, 'important'); 2042 }); 2043 } 2044 /* 2045 * Load uploaded fonts 2046 * 2047 */ 2048 self.loadPrivateFonts = function () { 2049 var apikey = self.options.apikey || false; 2050 //load private fonts 2051 self.xhrPost({ 2052 url: self.options.FFW_baseUrl + '/font/getuserfonts', 2053 data: { 2054 apikey: apikey, 2055 blogurl: fontBlogUrl, 2056 blogname: fontBlogName 2057 }, 2058 format: 'html' 2059 }, function (data) { 2060 self.$el.find('#uploaded').html(data); 2061 }); 2062 }; 2063 /* 2064 * Initialize font upload form 2065 */ 2066 self.initUploadForm = function () { 2067 $('body').on('submit', self.baseSelector + ' #fontUpload', function () { 2068 self.ajaxFontUpload.start(); 2069 }); 2070 }; 2071 /* 2072 * Upload font using ajax 2073 * 2074 */ 2075 self.ajaxFontUpload = (function () { 2076 return { 2077 start: function () { 2078 $('.fontUploadForm').hide(); 2079 $('.fontUploading').show(); 2080 $('#fontUploadIframe').load(function () { 2081 self.loadPrivateFonts(); 2082 //get info about the upload 2083 /*$.getJSON(self.options.FFW_baseUrl + '/font/wpaddsummary', function (data) { 2084 if (data.success === 'true') { 2085 self.loadPrivateFonts(); 2086 } else { 2087 alert('Font upload error. Check if file is not blocked against embedding.'); 2088 $('.fontUploadForm').show(); 2089 $('.fontUploading').hide(); 2090 } 2091 });*/ 2092 }); 2093 } 2094 }; 2095 }()); 2096 /* 2097 * 2098 * ELEMENT SELECTION AND CSS RULE GENERATION 2099 * 2100 */ 2101 /* 2102 * Enter element selection mode 2103 * 2104 * @param {type} add 2105 * @returns {unresolved} 2106 */ 2107 self.bindGetSelector = function (add) { 2108 //get selector 2109 var selector = self.currentPreset.selector; 2110 //add cancel button 2111 if (!self.$cancelSelecting) { 2112 self.$cancelSelecting = $('<a href="#" class="cancelSelecting">Stop selecting</a>'); 2113 $('body').append(self.$cancelSelecting); 2114 self.$cancelSelecting.data('cancelSelecting', true); 2115 //hide other elements 2116 self.$presets.hide(); 2117 } else { 2118 self.$cancelSelecting.show(); 2119 //hide other elements 2120 self.$presets.hide(); 2121 } 2122 $('a, button').on('click.selectionMode', function (e) { 2123 e.preventDefault(); 2124 self.handleSelectionClick($(this), add); 2125 return false; 2126 }); 2127 $('body').on('click.selectionMode', '*', function (e) { 2128 e.preventDefault(); 2129 self.handleSelectionClick($(this), add); 2130 return false; 2131 }); 2132 $('body').on('mouseover', '*', function () { 2133 if ($(this).data('cancelSelecting')) { 2134 return; 2135 } 2136 self.hoverSelector = self.getSelector(this); 2137 self.hoverHighlightCurrent(); 2138 $(this).css('outline', '3px dashed rgba(50,50,250,0.7)'); 2139 (function () { 2140 var element = $(this); 2141 setTimeout(function () { 2142 element.css('outline', 'none'); 2143 }, 100); 2144 }()); 2145 return false; 2146 }); 2147 $('body').on('mouseout', '*', function () { 2148 $(this).css('outline', 'none'); 2149 return false; 2150 }); 2151 }; 2152 /* 2153 * Enter selection mode 2154 * 2155 */
2156 self.handleSelectionClick = function ($el, add) { 2157 //if this is cancel selecting button 2158 if ($el.hasClass('cancelSelecting')) { 2159 self.stopSelectionMode(); 2160 self.reloadPreset(); 2161 return; 2162 } 2163 //if the element's preset is already created just pick it up 2164 if ($el.data('wired')) { 2165 self.$cancelSelecting.css('outline', 'none'); 2166 self.stopSelectionMode(); 2167 self.loadPreset($el.data('presetNo')); 2168 return false; 2169 } 2170 var sel = self.getSelector($el[0]), 2171 selectorInput, 2172 comma; 2173 //return false; 2174 //if not add to current preset mode 2175 if (!add) { 2176 self.stopSelectionMode(); 2177 var val = prompt('Name the selection i.e. title, header or paragraph. It\'ll be now listed in the upper left corner.'); 2178 //if not ask for new selection name 2179 if (!val) { 2180 self.bindGetSelector(add); 2181 return false; 2182 } else { 2183 //create a new preset of given selector 2184 self.createPreset(val, sel); 2185 } 2186 } 2187 self.outlineAllPresets(); 2188 selectorInput = self.getField('selector'); 2189 if (add) { 2190 comma = selectorInput.val() ? ', ' : ''; 2191 selectorInput.val(selectorInput.val() + comma + sel); 2192 } else { 2193 selectorInput.val(sel); 2194 } 2195 selectorInput.trigger('change'); 2196 self.stopSelectionMode(); 2197 self.highlightCurrent(); 2198 //load preset again to apply changes to a new element 2199 if (add) { 2200 self.reloadPreset(); 2201 } 2202 }; 2203 /* 2204 * Exit element selection mode 2205 * 2206 * @param {type} htmlcol 2207 * @returns {rgb} 2208 */ 2209 self.stopSelectionMode = function () { 2210 $('body').off('mouseover', '*'); 2211 $('body').off('click.selectionMode', '*'); 2212 $('a').off('.selectionMode'); 2213 $('button').off('.selectionMode'); 2214 $(this).css('outline', 'none'); 2215 $('body').off('mouseout', '*'); 2216 self.$cancelSelecting.hide(); 2217 //hide other elements 2218 self.$presets.show(); 2219 }; 2220 /* 2221 * Generate CSS selector for passed element 2222 * 2223 * @param {type} element 2224 * @returns {selector} 2225 */ 2226 self.getSelector = function (element) { 2227 var selector = $(element).parents() 2228 .map(function () { 2229 return this.tagName; 2230 }) 2231 .get().reverse().join(" "), 2232 id, 2233 classNames, 2234 selectorsArr, 2235 sel, 2236 parents = [], 2237 selectors = []; 2238 //go through each mapped object and get id class etc 2239 for (var i = 0; 2240 (i < $(element).parents().length && i < 4); i++) { 2241 var $parent = $(element).parents().eq(i), 2242 parentSelector = $parent[0].nodeName; 2243 //classses only for first 3 parents(now it's reversed) 2244 if (i < 2) { 2245 //get id 2246 //if (id = $parent.attr('id')) { 2247 // parentSelector += '#' + id; 2248 //} 2249 //class names 2250 classNames = $parent.attr("class"); 2251 if (classNames) { 2252 parentSelector += "." + $.trim(classNames).replace(/\s/gi, "."); 2253 } 2254 } 2255 selectors.push(parentSelector); 2256 } 2257 selector = selectors.reverse().join(' '); 2258 //get element tagname 2259 if (selector) { 2260 selector += " " + $(element)[0].nodeName; 2261 } 2262 id = $(element).attr("id"); 2263 if (id) { 2264 selector += "#" + id; 2265 } 2266 classNames = $(element).attr("class"); 2267 if (classNames) { 2268 selector += "." + $.trim(classNames).replace(/\s/gi, "."); 2269 // remove ui-draggable when re-selecting element with once removed draggability 2270 //ui-draggable 2271 } 2272 return selector; 2273 }; 2274 /* 2275 * Scroll to selected element 2276 * 2277 * @returns {unresolved} 2278 */ 2279 self.scrollToSelection = function () { 2280 var selector = self.currentPreset.selector, 2281 container, 2282 found; 2283 container = $('body'); 2284 //exit when default selector 2285 if (selector.indexOf('ELEMENT NOW') !== -1 || selector.indexOf('PICK ELEMENT') !== -1) { 2286 return; 2287 } 2288 //get by selector from the iframe 2289 found = container.find(selector); 2290 //scroll to the top when no el selected 2291 if (!found.length) { 2292 return; 2293 } 2294 //animate scroll 2295 $('html, body').animate({ 2296 scrollTop: (parseInt(found.offset().top, 10) - 150) 2297 }, 'slow'); 2298 }; 2299 /* 2300 * Highlight current element on hover 2301 */ 2302 self.hoverHighlightCurrent = function () { 2303 var selector = self.hoverSelector; 2304 if (self.tempHightlighted) { 2305 self.tempHightlighted.css('outline', 'none'); 2306 } 2307 //exit when default selector 2308 if (selector.indexOf('ELEMENT NOW') !== -1 || selector.indexOf('PICK ELEMENT') !== -1) { 2309 return; 2310 } 2311 self.tempHightlighted = $(selector); 2312 self.tempHightlighted.css('outline', '3px dashed rgba(100,250,100,0.7)'); 2313 }; 2314 /* 2315 * highlight all elements(with edititng option) 2316 */ 2317 self.outlineAllPresets = function () { 2318 //go through all presets 2319 for (var i = 0; i < self.options.presets.length; i++) { 2320 if (parseInt(i, 10) === parseInt(self.currentPresetNo, 10)) continue; 2321 var preset = self.options.presets[i]; 2322 var selector = preset.selector; 2323 //exit when default selector 2324 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 2325 continue; 2326 } 2327 var litme = $(selector); 2328 litme.css('outline', '2px dashed rgba(150,150,250,0.3)'); 2329 $('.deletePreset').remove(); 2330 litme.css("cursor", 'pointer', 'important'); 2331 if (litme.data('wired') === true) { 2332 continue; 2333 } 2334 litme.data('wired', true); 2335 (function () { 2336 var ind = i; 2337 litme.data('presetNo', ind); 2338 litme.click(function (e) { 2339 // onbeoforeunload helps here 2340 //e.preventDefault(); 2341 if (parseInt($(this).data('presetNo'), 10) !== parseInt(self.currentPresetNo, 10)) { 2342 e.preventDefault(); 2343 self.loadPreset(ind); 2344 } 2345 }); 2346 litme.hover( 2347 function () { 2348 if (parseInt($(this).data('presetNo'), 10) !== parseInt(self.currentPresetNo, 10)) { 2349 $(this).css('outline', '2px dashed rgba(150,150,250,0.9)'); 2350 } 2351 }, 2352 function () { 2353 if (parseInt($(this).data('presetNo'), 10) !== parseInt(self.currentPresetNo, 10)) { 2354 $(this).css('outline', '2px dashed rgba(150,150,250,0.3)'); 2355 } 2356 } 2357 ); 2358 }()); 2359 } 2360 }; 2361 /* 2362 * highlight current 2363 * @returns {unresolved} 2364 */ 2365 self.highlightCurrent = function () { 2366 var selector = self.currentPreset.selector, 2367 btn; 2368 self.outlineAllPresets(); 2369 //exit when default selector 2370 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 2371 return; 2372 } 2373 self.hightlighted = $(selector); 2374 self.hightlighted.css('outline', '3px dashed rgba(250,50,30,0.7)'); 2375 self.hightlighted.style("cursor", 'move', 'important'); 2376 if(!self.hightlighted.find('.deletePreset')[0]) { 2377 btn = $('<button class="deletePreset">X</button>') 2378 self.hightlighted.append(btn); 2379 btn.click(function (e) { 2380 e.preventDefault(); 2381 self.deleteCurrentPreset(); 2382 return false; 2383 }); 2384 } 2385 self.makeCurrentDraggable(); 2386 }; 2387 /* 2388 * Removes highlighting from current element 2389 * 2390 * @returns {unresolved} 2391 */ 2392 self.unhighlightCurrent = function () { 2393 var selector = self.currentPreset.selector; 2394 self.outlineAllPresets(); 2395 //exit when default selector 2396 if (selector.indexOf('ELEMENT NOW') != -1 || selector.indexOf('PICK ELEMENT') != -1) { 2397 return; 2398 } 2399 self.hightlighted = $(selector); 2400 self.hightlighted.css('outline', 'none'); 2401 self.hightlighted.style("cursor", ''); 2402 //self.removeCurrentDraggable(); 2403 // remove draggable 2404 self.hightlighted.draggable("destroy"); 2405 }; 2406 /* 2407 * make current element draggable 2408 */ 2409 self.makeCurrentDraggable = function () { 2410 var isMozilla = $.browser && $.browser.mozilla; 2411 self.hightlighted.draggable({ 2412 drag: function (event, ui) { 2413 var top = ui.position.top, 2414 left = ui.position.left, 2415 $el = self.hightlighted; 2416 $el.each(function () { 2417 //set position to relative 2418 $(this).style("position", 'relative', 'important'); 2419 //set slider y to dragged value (parseInt(top,10) + parseInt($(window).scrollTop(),10)) 2420 //for firefox only 2421 if (isMozilla) { 2422 self.updateCssSettings('top', (parseInt(top, 10) + parseInt($(window).scrollTop(), 10)) + 'px'); 2423 } else { 2424 self.updateCssSettings('top', top + 'px'); 2425 } 2426 //set slider x to dragged value 2427 self.updateCssSettings('left', left + 'px'); 2428 //set position to relative 2429 self.updateCssSettings('position', 'relative'); 2430 }); 2431 //waiting to set top and left to "!important" after jquery ui draggable 2432 setTimeout(function () { 2433 $el.each(function () { 2434 //for firefox only 2435 if (isMozilla) { 2436 $(this).style("top", (parseInt(top, 10) + parseInt($(window).scrollTop(), 10)) + 'px', 'important'); 2437 } else { 2438 $(this).style("top", top + 'px', 'important'); 2439 } 2440 //set slider x to dragged value 2441 $(this).style("left", left + 'px', 'important'); 2442 }); 2443 }, 10); 2444 } 2445 }); 2446 }; 2447 /** 2448 * 2449 * COLOR CONVERSION FUNCTIONS 2450 * 2451 */ 2452 /* 2453 * Convert from HEX/HTML to rgb object 2454 * 2455 * @param {type} htmlcol 2456 * @returns {rgb} 2457 */ 2458 self.html2rgb = function (htmlcol) { 2459 var rgb = new Object(); 2460 rgb.r = self.html2dec(htmlcol.substr(0, 2)); 2461 rgb.g = self.html2dec(htmlcol.substr(2, 2)); 2462 rgb.b = self.html2dec(htmlcol.substr(4, 2)); 2463 return rgb; 2464 }; 2465 /* 2466 * Parse RGB to HTML to 2467 * @param {type} rgbString 2468 * @returns {@exp;self@call;html2rgb} 2469 */ 2470 self.parseRgb = function (rgbString) { 2471 return self.html2rgb(self.rgbString2hex(rgbString)); 2472 }; 2473 self.rgbString2hex = function (rgbString) { 2474 var parts = rgbString.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); 2475 // parts now should be ["rgb(0, 70, 255", "0", "70", "255"] 2476 if (!parts) return '000000'; 2477 delete(parts[0]); 2478 for (var i = 1; i <= 3; ++i) { 2479 parts[i] = parseInt(parts[i]).toString(16); 2480 if (parts[i].length == 1) parts[i] = '0' + parts[i];
2481 } 2482 var hexString = parts.join(''); 2483 return hexString; 2484 }; 2485 /* 2486 * Converts color from HEX/HTML-style (00-FF) to decimal color value (0-255) 2487 */ 2488 self.html2dec = function (h) { 2489 return parseInt(h, 16); 2490 }; 2491 /* 2492 * 2493 * MODAL WINDOWS AND OVERLAYS 2494 * 2495 */ 2496 /* 2497 * Create new modal window 2498 */ 2499 self.createNewModal = function (options) { 2500 var modal = $('<div class="draggableModal"><h1 class="draggableModalBar">' + options.title + '<a class="closeModal" href="#">x</a></h1></div>'); 2501 modal.css({ 2502 left: options.left ? options.left : 'auto', 2503 right: options.right ? options.right : 'auto', 2504 top: options.top, 2505 width: options.width, 2506 position: 'fixed', 2507 zIndex: 1000000 2508 }); 2509 if (options.nobar) { 2510 modal.find('h1.draggableModalBar').hide(); 2511 } 2512 if (!options.show) { 2513 modal.hide(); 2514 } 2515 if (options.id) { 2516 modal.attr('id', options.id); 2517 } 2518 self.modals[options.name] = modal; 2519 2520 //make draggable 2521 modal.draggable({ 2522 handle: modal.find('.draggableModalBar'), 2523 start: function () { 2524 $(this).css('bottom', 'auto'); 2525 } 2526 }); 2527 2528 modal.find('.closeModal').click(function () { 2529 modal.hide(); 2530 return; 2531 }); 2532 modal.appendTo($('body')); 2533 //self.modalToTop(modal); 2534 return modal; 2535 }; 2536 /* 2537 * create a popup with content for overlay links 2538 * 2539 * @returns {unresolved} 2540 */ 2541 self.bindLinkOverlay = function () { 2542 $('body').on('click', 'a.font_url, a.overlay_url, button.overlay_url', function () { 2543 var modal, 2544 frameSrc, 2545 iframe, 2546 overlay, 2547 href = $(this).attr('href'); 2548 if ($(this).attr('data-upgrade') === 'true') { 2549 self.setupApikeyCheckingInterval(); 2550 } 2551 //create overlay 2552 overlay = $('<div id="memberOverlay"></div>'); 2553 overlay.appendTo(document.body); 2554 overlay.css({ 2555 position: 'fixed', 2556 top: 0, 2557 left: 0, 2558 width: '100%', 2559 height: '100%', 2560 'background-color': '#333',
2561 filter: 'alpha(opacity=50)', 2562 '-moz-opacity': 0.5, 2563 '-khtml-opacity': 0.5, 2564 opacity: 0.5, 2565 'z-index': 200000001 2566 }); 2567 modal = $('<div class="draggableModal ui-draggable"><h1 class="draggableModalBar">' + href + ' <a class="closeModal" href="#">x</a></h1></div>'); 2568 modal.css({ 2569 position: 'fixed', 2570 left: '-475px', 2571 marginLeft: '50%', 2572 width: '950px', 2573 top: '40px', 2574 zIndex: 200000001 2575 }); 2576 modal.find('.closeModal').bind('mousedown', function () { 2577 modal.remove(); 2578 overlay.remove(); 2579 return; 2580 }); 2581 frameSrc = href; 2582 iframe = $('<iframe style="width:98%; height:490px; border:none; margin: 10px 1%" frameBorder="0" src="' + frameSrc + '"></iframe>'); 2583 iframe.appendTo(modal); 2584 modal.appendTo($('body')).show(); 2585 overlay.click(function () { 2586 modal.remove(); 2587 $(this).remove(); 2588 }); 2589 return false; 2590 }); 2591 return; 2592 }; 2593 /* 2594 * adapt plugin looks to different modes - global or post page 2595 */ 2596 self.adaptOptionsToMode = function () { 2597 if (self.mode === 'postPage') { 2598 self.settingFields.presets.hide(); 2599 self.$presets.hide(); 2600 self.$apr.show(); 2601 self.settingFields.selector.hide(); 2602 $('#fontSaveSettings').hide(); 2603 $('#effectsButton').hide(); 2604 } 2605 }; 2606 /* 2607 * Show hide modal 2608 * 2609 * @param {type} modalName 2610 */ 2611 self.toggleModal = function (modalName) { 2612 if (self.modals[modalName] === undefined) { 2613 return; 2614 } 2615 // if this is effects button 2616 if (modalName === 'effects') { 2617 // detect CSS text-shadow support in JavaScript 2618 if (document.createElement("detect").style.textShadow !== "") { 2619 alert('Sorry, but your browser does not support advanced effects. Please upgrade to Chrome, Firefox or Internet Explorer 10'); 2620 return; 2621 } 2622 } 2623 self.modals[modalName].toggle(); 2624 self.modalToTop(self.modals[modalName]); 2625 }; 2626 /* 2627 * Put modal on top 2628 * 2629 * @param {type} selectedModal 2630 */ 2631 self.modalToTop = function (selectedModal) { 2632 var highestZindex = 1000000; 2633 for (var index in self.modals) { 2634 var modal = self.modals[index], 2635 modalZindex = modal.css('zIndex'); 2636 if (parseInt(modalZindex, 10) > parseInt(highestZindex, 10)) { 2637 highestZindex = modalZindex; 2638 } 2639 } 2640 $(selectedModal).css({ 2641 'zIndex': parseInt(highestZindex, 10) + 1 2642 }); 2643 }; 2644 /* 2645 * 2646 * TINY MCE EDITOR 2647 * 2648 */ 2649 /* 2650 * set font for post or page in tinymce 2651 */ 2652 self.setTinyMCEFont = function (fontId, fontName) { 2653 //get selection 2654 var selection = tinyMCE.activeEditor.selection.getContent(), 2655 selectorValid, 2656 $selectorContents, 2657 fontClass, 2658 node, 2659 newSpan, 2660 newHTML, 2661 inserted, 2662 $tempDiv, 2663 multipleSelectors; 2664 //only apply if something is selected 2665 if (!selection) { 2666 return; 2667 } 2668 //get node 2669 fontClass = "fontplugin_fontid_" + fontId + "_" + fontName; 2670 node = tinyMCE.activeEditor.selection.getNode(); 2671 //selectorValid - validate selector created from selected text. 2672 //required because for example "." with nothing following breaks function execution 2673 selectorValid = true; 2674 try { 2675 $selectorContents = $(selection); 2676 } catch (e) { 2677 selectorValid = false; 2678 } 2679 if (selectorValid && $selectorContents.length > 1) { 2680 selectorValid = false; 2681 multipleSelectors = true; 2682 } 2683 if (selectorValid && ($.trim($(node).html()) === $.trim(selection) || $.trim($(node).html()) === $.trim($(selection).html()))) { 2684 //console.log('already isolated'); 2685 tinyMCE.activeEditor.dom.setAttrib(node, 'class', fontClass); 2686 } else if (multipleSelectors) { 2687 $selectorContents.each(function () {
2688 $(this).removePrefixedClasses('fontplugin_fontid_'); 2689 $(this).addClass(fontClass); 2690 2691 $(this).attr('class').split(' '); 2692 }); 2693 $tempDiv = $('<div>').append($selectorContents); 2694 newHTML = $tempDiv.html(); 2695 2696 inserted = tinyMCE.activeEditor.selection.setContent(newHTML); 2697 } else { 2698 newSpan = $("<span class=\"" + fontClass + "\">" + selection + '</span>'); 2699 //get span html together with span itself 2700 newHTML = $('<div>').append(newSpan.clone()).html(); 2701 //add font in use 2702 inserted = tinyMCE.activeEditor.selection.setContent(newHTML); 2703 tinyMCE.activeEditor.selection.select(tinyMCE.activeEditor.dom.select('span.' + fontClass)[0]); 2704 } 2705 //loads font face to iframe editor 2706 self.loadFontFace(fontId); 2707 }; 2708 /* 2709 * Load font to tinymce iframe 2710 */ 2711 self.loadFontFace = function (fontId) { 2712 var head = self.postIframe[0].getElementsByTagName('head')[0], 2713 linkElement = $(document.createElement('link')); 2714 linkElement.attr({ 2715 href: self.options.FFW_baseUrl + '/font/generatepreviewcss/?id=' + fontId, 2716 rel: 'stylesheet', 2717 type: 'text/css' 2718 }); 2719 linkElement.appendTo(head); 2720 }; 2721 /* 2722 * 2723 * UTILITY FUNCTIONS 2724 * 2725 */ 2726 /* 2727 * execute cross domain request, JSON response 2728 * 2729 * @param {type} params 2730 * @param {type} callback 2731 * @returns {@exp;$@call;post} 2732 */ 2733 self.xhrPost = function (params, callback) { 2734 var data = params; 2735 if (params.format === undefined) { 2736 params.format = 'json'; 2737 } 2738 data.action = 'cross_domain_request'; 2739 2740 return $.ajax({ 2741 type: "POST", 2742 url: ajaxproxy, 2743 data: data, 2744 success: function (response) { 2745 if (typeof callback === 'function') { 2746 callback(response); 2747 } 2748 }, 2749 dataType: params.format, 2750 error: function (xhr, textStatus, errorThrown) { 2751 alert("An error occurde. This might be a conflict with another plugin. Error message: " + textStatus); 2752 } 2753 }); 2754 }; 2755 /* 2756 * show loading spinner 2757 */ 2758 self.showLoading = function () { 2759 if ($('.fontLoading').length) { 2760 //self.$apr.find('fieldset').hide(); 2761 //self.$el.find('> div').hide(); 2762 $('.fontLoading').show(); 2763 $('.fontLoading').show(); 2764 } else { 2765 $('body').append('<div class="fontLoading"></div>'); 2766 } 2767 }; 2768 /* 2769 * hide loading spinner 2770 */ 2771 self.hideLoading = function () { 2772 $('.fontLoading').hide(); 2773 $('.fontLoading').hide(); 2774 }; 2775 /* 2776 * detect if we're on post editing page or on any other page 2777 */ 2778 self.detectMode = function () { 2779 var iframe = $('#content_ifr'); 2780 if (iframe.length) { 2781 self.mode = 'postPage'; 2782 self.postIframe = iframe.contents(); 2783 //self.tinyMCE = $(self.postIframe).find('#tinymce'); 2784 } else { 2785 self.mode = 'global'; 2786 } 2787 // detect CSS text-shadow support in JavaScript 2788 if (document.createElement("detect").style.textShadow === "") { 2789 self.shadowSupport = true; 2790 } else { 2791 self.shadowSupport = false; 2792 } 2793 }; 2794 // finally INIT 2795 self.init(); 2796 }; 2797 /* 2798 * set default options 2799 */ 2800 $.fontPlugin.defaultOptions = { 2801 FFW_baseUrl: 'http://fontsforweb.com' 2802 }; 2803 /* 2804 * make jquery plugin 2805 */ 2806 $.fn.fontPlugin = function (options) { 2807 return this.each(function () { 2808 var fontPlugin = new $.fontPlugin(this, options); 2809 }); 2810 }; 2811 /* 2812 * HANDLE PLUGIN 2813 * 2814 * options 2815 * startX -vstarting position 2816 * startY -vstarting position 2817 * name - handle name 2818 * label - visible label 2819 * 2820 */ 2821 var XYSlider = function (el, options) { 2822 var self = this; 2823 self.$el = $(el); 2824 self.$el.data('XYSlider', self); 2825 // immediate init funciton 2826 self.init = function () { 2827 // get handle element by name 2828 var handleHolder = self.$el.data(options.settingName), 2829 handle = (handleHolder && handleHolder[0]) ? handleHolder.find('.XYSlider')
2829: false; 2830 // if doesn't exist create the handle 2831 if (!handleHolder || !handleHolder[0]) { 2832 handleHolder = $('<div class="XYSliderHolder"></div>'); 2833 handle = $('<div class="XYSlider">' + options.label + '</div>'); 2834 handleHolder.append(handle); 2835 self.$el.append(handleHolder); 2836 } 2837 self.$el.data(options.settingName, handleHolder); 2838 // save in object 2839 self.$handleHolder = handleHolder; 2840 self.$handle = handle; 2841 // make handle draggable 2842 handle.each(function () { 2843 // show handle 2844 $(this).parent().show(); 2845 // make draggable 2846 $(this).draggable({ 2847 drag: function (event, ui) { 2848 var top = ui.position.top, 2849 left = ui.position.left, 2850 // revert top: more is higher 2851 y = -top, 2852 x = options.invertX ? -left : left; 2853 self.commitDrag(x, y, true); 2854 } 2855 }); 2856 }); 2857 }; 2858 /* 2859 * Change position of draggable 2860 * 2861 * x - x position 2862 * y - y position 2863 */ 2864 self.setPosition = function (x, y) { 2865 var handle = self.$handle; 2866 2867 if (x !== false) { 2868 self.x = x; 2869 } else if (self.x === undefined) { 2870 x = 0; 2871 self.x = 0; 2872 } else { 2873 x = self.x; 2874 } 2875 if (y !== false) { 2876 y = y; 2877 self.y = y; 2878 } else if (self.y === undefined) { 2879 y = 0; 2880 self.y = 0; 2881 } else { 2882 y = self.y; 2883 } 2884 if (x === false && y === false) { 2885 return; 2886 } 2887 // move x and y - revert top: more is higher 2888 handle.css({ 2889 'top': -y + 'px', 2890 'left': (options.invertX ? -x : x) + 'px' 2891 }); 2892 // commit drag 2893 self.commitDrag(x, y, true); 2894 }; 2895 /* 2896 * Execute callbacks 2897 */ 2898 self.commitDrag = function (x, y, stop) { 2899 var rad = Math.atan2(x, y), 2900 deg = rad * (180 / Math.PI), 2901 distance = 0; 2902 if (stop === undefined) { 2903 stop = false; 2904 } 2905 //get angle 2906 if (deg < 0) { 2907 deg = 360 + deg; 2908 } 2909 // round angle to full degrees 2910 deg = Math.round(deg); 2911 // calculate distance 2912 distance = Math.sqrt(x * x + y * y); 2913 // set current values 2914 self.setCurrentValues(x, y, deg, distance); 2915 // call actions 2916 options.actions.call(this, x, y, deg, distance); 2917 }; 2918 self.setCurrentValues = function (x, y, deg, distance) { 2919 self.x = x; 2920 self.y = y; 2921 self.deg = deg; 2922 self.distance = distance; 2923 return self; 2924 }; 2925 self.getCurrentValues = function () { 2926 return { 2927 'x': self.x, 2928 'y': self.y, 2929 'deg': self.deg, 2930 'distance': self.distance 2931 }; 2932 }; 2933 self.init(); 2934 }; 2935 // use prototype 2936 $.fn.XYSlider = function (options) { 2937 return this.each(function () { 2938 //new XYSlider(this, options); 2939 //var pluginName = 'XYSlider'; 2940 new XYSlider(this, options); 2941 }); 2942 }; 2943}(jQuery));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.