Leaderboard
Popular Content
Showing content with the highest reputation on 08/18/2016 in all areas
-
I pushed an initial (testing) version of TemplateFileHelper to bitbucket. https://bitbucket.org/pwFoo/templatefilehelper/src/ The autoload module extends TemplateFile instances with API vars $layout and $view $layout -> global layout instance of TemplateFile to set layout placeholders ($layout->set(...) or global scripts / styles. $view -> current page instance of TemplateFile to set the current page placeholders and current page scripts / styles. load() method Load a template / view with additional controller (php) file as subTemplate. Returns a TemplateFile object to render / output Each sub-template controller have access to API Vars and $subTemplate (current TemplateFile instance, $subTemplate->set('placeholder', 'My value...')). Load site/templates/chunks/test1.php controller and site/templates/chunks/test1.tpl view: $part = $view->load('chunks/test1'); echo $part->render(); chunks/test1 example <?php // chunks/test1.php - controller $subTemplate->set('var1', "Subtemplate variable output..."); <!-- chunks/test1.tpl - view --> <div><?=$var1?></div> scripts / styles properties FilenameArray like $config->styles | scripts. It should help to organize scripts / styles with ajax in mind (global / current page only). // current page script $view->scripts->add('js-file.js'); // global / layout script $layout->scripts->add('js-file.js'); You have to handle the output yourself by two foreach loops inside your _layout.php / _layout.tpl files (non ajax calls scripts and styles should be in layout head section). foreach ($layout->scripts as $globalScript) { ... } foreach ($view->scripts as $currentPageScript) { ... } IntercoolerJS module will take care about async / ajax handling of (custom page) scripts and styles. hook Page::render hook after page render to load and add the global layout. The current page template (PW template file == controller) just handle the currents page code / view. Global layout / controller / view is moved to separate files (default: _layout.php controller and _layout.tpl view). Just use $layout->set(...) to fill the _layout.tpl placeholder variables inside the _layout.php controller file. configurable module Some settings are available... Global layout (view + controller) file name (default: "_layout") Current page content variable (used inside of the _layout.tpl view to output current page content, default: "currentPageContent") View file extension (default: ".tpl") Controller file extension (default: ".php") It will be a dependency of the planned IntercoolerJS module which adds ajax page calls, async scripts / styles handling (current page scripts and styles...) and need a defined template handling to work...4 points
-
Yep, ajax did not work out, it is in iframe indeed. So checking for the process is the option to choose. I managed to write a few lines in ready.php to handle the case: if($page->template == "admin") { if($user->hasRole("editor")) { if(!($page->process == "ProcessPageEdit" && $input->get->id == $currentCity->id)) { $session->redirect("/"); } } } This way the admin login page stays accessible for everyone, but almost everything else is not for the user with editor role. The page with the process ProcessPageEdit is accessible as it is needed for frontend editing, but only under certain conditions (actually only one page is editable).4 points
-
the way i do it is to create a Runtime Markup field that outputs a value, for example the name of container page template; then you can reference that value in your conditional visibility.2 points
-
@tony Hi, I have already tried to install the version found in the modules directory, but this one did not work for me either: http://modules.processwire.com/modules/blog-profile/ Instead, try the version posted by Ryan here (this one worked): Note: you might want to install it along with a ProcessWire version close to its release date, or at least ProcessWire 2.7 or 2.8. It might work with 3.x too but I have never tried. One more tip: you might also be interested in this one by @clsource for ProcessWire 3.x:2 points
-
Hello tpr, thanks for your help! I got it working with this code: <script> $("#mainlogin-form").on('submit', function(e){ e.preventDefault(); $.ajax({ type: "POST", url: "<?php echo $pages->get('template=login')->url;?>", data: $("#mainlogin-form").serialize(), success: function(data){ window.location.href = "<?php echo $pages->get("template=profile")->url;?>"; } }); return false; }); </script> For all others who are interested in: First step: I prevent the page reload with e.preventDefault() - this is necessary to prevent the reload, otherwise you will not get logged in Second step: I made a Ajax request to my login template, where the form will be processed (validation stuff, login process,...) url: the url to my login page data : serialize all the form inputs that should be sent with the Ajax request. success: if all is alright then force a redirect to the profile page Best regards2 points
-
Finally I found it. It seems a conflict with the module Image Extra, which I installed previously, once uninstalled the animated gif is uploaded without problem.2 points
-
v047 is up with improvements to the Pagelist thumbs submodule. Thumbnails can be aligned to the right so they don't create ragged lines of the page titles if there's no image or the images are of different widths: Of course this partly could be eliminated if using the "circle" or "square" styles: You can set the thumbnails to link to the edit page if you wish. Another addition is that if a multi-image field is specified as the image source, its first image will be used.2 points
-
Here is an example, how you could use Responsive Images with srcset for retina images in combination with lazysizes: <?php $image = $page->image->size(800, 600); $imageRetina = $page->image->size(1600, 1200); echo " <img class='lazyload' src='{$config->urls->templates}images/1x1.gif' data-sizes='auto' data-src='{$image->url}' data-srcset='{$image->url}, {$imageRetina->url} 2x' width='{$image->width}' height='{$image->height}' alt='{$page->image->description}'> "; It is not that difficult, but you have to get used to the markup. Also be sure to check on different devices, if it actually works (for example retina devices). The Chrome developer tools are also good in debugging Responsive Images.2 points
-
I've just posted a Fieldtype and Inputfield module combination that support the use of MySQL time fields in ProcessWire. Ryan's Datetime module is great but I needed something that dealt specifically with times for a scheduling system and this is one of the results. For 24 hour clock format ('HH24MM') you now get a clock-picker pop-up by default... ...but you can inhibit it if you don't want it... Although the input time format is selectable, as this is stored as a MySQL time field, you currently need to specify values in selectors in full "H:MM:SS" format. So if you wanted to get all events starting on or after 9am you'd do something like this... $events = $pages->find("template=events, starts>=9:00:00")->sort("starts"); This is definitely a beta module as I've not tested every single input format yet. Currently does not support negative time-periods or fractions of a second. FieldtypeTime on Github FieldtypeTime in the Module Repository Releases Version 0.2.0: Adds support for the use of this input field in repeaters and repeater matrix types. Version 0.1.0: Adds clock picker.1 point
-
About a month ago I announced UserGroups module, which I gave humble beginning, but Nik and Teppo really pushed forward (not sure if there is anything of my original code left anymore...). We are getting closer to initial 1.0 release feature wise, so this is good time to get more feedback from you guys. We have been focusing on finding all the different situations, where user access is defined and finding the right balance of features and simplicity. I am pretty sure there must be some cases where this module fails, so please do test all kind of combinations you can imagine and hunt some bugs! Grab the module from here and install it on big, popular and complex live site and go wild (or actually.. maybe not): https://github.com/apeisa/UserGroups/ Module is based on groups instead of roles. Idea here is that groups are something that your client can manage, but roles & permissions are not. There is no documentation or tutorial yet, but just install it - I think you will figure it soon (just create few groups, look for access tab on pages and try). Also check out this companion module that Teppo has build. It allows access management right from page tree: https://github.com/Aldone/PageListPermissions/1 point
-
Wire Queue Wire Queue is a module that allows easy creation and usage of Queues in ProcessWire. It is based upon a basic parent module (WireQueue) that should have one or multiple StorageHandler modules installed too. This beta release contains a simple plain text storage module, WireQueueTextfile, and a simple Sqlite3-DB storage module, WireQueueSqlite3. The base module creates the needed: FIELDS (wire_queue_type, wire_queue_state, wire_queue_storage_options) TEMPLATES (wire-queue-container, wire-queue-storage, wire-queue-tools) PAGES (wire-queues = container for all Queuepages, wire-queue-storages = container for StoragetypePages) ROLE (wire-queue-admin) Each storage module creates one page under wire-queue-storages. New Queues can be created in the backend by adding a new page under "Wire Queues". After creation one have to select a Storage type from availables list and publish the page. After that, there are some buttons available to start / pause / and close the queue. Putting and getting data to and from the queue is done via API calls. First you have to get the page that holds the queue object. // get and validate the queue handle if($queue = $pages->get(SELECTOR_TO_DESIRED_PAGE)->wireQueue()) { // wrap your data into an array and pass it into the queue $success = $queue->addItem($data); ... } // get and validate the queue handle if($queue = $pages->get(SELECTOR_TO_DESIRED_PAGE)->wireQueue()) { $data = $queue->getItem(); ... } Thats basically all what you want from a queue. Following are a few conveniences: $queue->getPage()->title gives you the title of the queue, ($queue->getPage() returns the page object) $queue->className() shows the StorageType of the queue $queue->getState() and $queue->getStateStr() returns the current state of a queue: 1 = new / empty 2 = enabled / running 3 = paused 4 = closed / archived $queue->itemCount() gives the total number of all pending items in the queue Here is code that gives an overview of all Queues in the system: $container = $pages->get('template=wire-queue-container'); $bodyContent = "<h1>$container->title</h1>"; $bodyContent .= "<p>There are currently {$container->numChildren} Queues defined:</p>"; $bodyContent .= "<ul>"; foreach($container->children() as $p) { if(! ($queue = $p->wireQueue())) continue; $bodyContent .= "<li>{$queue->getPage()->title}<ul>"; if(!$queue->ready2use()) { $bodyContent .= "<li>{$queue->className}</li>"; $bodyContent .= "<li>This Storagetype is not ready to use! The System seems not to provide all requirements.</li>"; $bodyContent .= "</ul></li>"; continue; } $bodyContent .= "<li>{$queue->className}</li>"; $bodyContent .= "<li>{$queue->getStateStr()} ({$queue->getState()})</li>"; $bodyContent .= "<li>Currently are {$queue->itemCount()} items pending!</li>"; $bodyContent .= "</ul></li>"; } $bodyContent .= "</ul>"; Following is a screenshot of the backend The module is available in the modules directory: http://modules.processwire.com/modules/wire-queue/ Or you get it from Github: https://github.com/horst-n/WireQueue. . . . The Sqlite3 storage handler not only let you push and pull data items to and from it, it also can keep track of the current state of a record. If you use multiple / different workers for pulling and processing the data, you can store an ID for them too. This is how the DB Table looks like: The Wire Queue Sqlite3 storage handler provides the methods addItem($arrayData) // same as WireQueueTextfile getItem($worker = null) // same as WireQueueTextfile, (but the textfile storage cannot support $worker!) updateItemState($id, $state, $worker = null) // this you can use for further processing, if you want . addItem($arrayData) $arrayData is a, maybe associative, array containing all your data for one record. The method stores it under the next free id under data in the Sqlite-DB-file and sets the state to 0. The field worker is empty for new added records. Following is a basic working example for pushing data records into a queue: // you have created a queue in PW, the ID of the page is 1420 for example // here is some skeleton code for an importer that uses this queue // get and validate the queue handle if(! ($queue = $pages->get('id=1420')->wireQueue())) exit(); // we could not get the Queuepage // now start to scan / read data for your imports, wrap each record into an array and put it into the queue foreach($pages->find(YOURSELECTOR) as $p) { $data = array($p->field1, $p->field2); $queue->addItem($data); } . . getItem($worker = null) $worker is an integer that you can define to suite your needs. If you don't use or don't want identify multiple workers, just ommit it. The method pulls one pending record from the queue, changes the state from 0 to 1, and returns an associative array with the keys id and data. array('id' => integer, 'data' => array) You will need the id if you further want to use the queue to keep track of processing steps. You must pull your stored $data from $array['data'] and use the id for further storing the state. . updateItemState($id, $state, $worker = null) $id identifys the record a worker has processed, for $state you can define and use every integer you like, but not 0 or 1. If you also want to store altered data, and not only different states, you can use updateItem($id, $state, $worker = null, $data = null) instead of updateItemState(). . Here is a working example with a bit pseudo code how workers can get a pending record to process it further and store back the result of the process: // you have created a queue in PW, the ID of the page is 1420 for example // here is some skeleton code for an importer that uses this queue // get and validate the queue handle if(! ($queue = $pages->get('id=1420')->wireQueue())) exit(); // we could not get the Queuepage // we do not use different workers here in that example, so we do not pass an worker id here $tmp = $queue->getItem(); // get a record from the queue $record_id = $tmp['id']; // store the record id $data = $tmp['data']; // get the data array // process the $data ... // and get the result of the process, in this example true or false $result = processMyRecord($data); // as new records have a state = 0, fetched records have a state = 1, // you may define a state of 2 for successful processed records, and higher ones for failed records $state = true === $result ? 2 : 3; $queue->updateItemState($record_id, $state); . . getItem4FurtherProcessing($state, $worker = null) The $state you pass to the method is the state you want get the record for. If there is one pending, its state will be set +1 and the id and data is passed back to you in an associative array: array('id' => integer, 'data' => array). --------- Here is a pseudo code example how (multiple) worker scripts may batch process queue records with the sqlite storage handler // on the server in this example, everyscript will timeout / die after 180 seconds // we start a timer $time = Debug::timer(); // we use different instances of workers that pull and process records from the queue, // so additionally to the processings states, we also want to store the worker ids $worker = 2000; // now start to process items by pulling one after the other from the queue while(150 > Debug::timer($time)) { $tmp = $queue->getItem($worker); // get a record from the queue if(!$tmp) continue; // maybe currently are no pending records available $record_id = $tmp['id']; // store the record id $data = $tmp['data']; // get the data array $result = processMyRecord($data); // process the data and get back the result $state = true === $result ? 2 : 3; // define an integer for the new state, according to the result of processing the data $queue->updateItemState($record_id, $state, $worker); } // we are close to the timeout for the script, so finish it with calling it itself to get a fresh run $session->redirect('./');1 point
-
I'm developing single-page application (SPA) which interacts with PW site only with help of ajax post/get calls to custom site API. Initially guest (non-loggeding) user opens page with SPA. Then he logins via ajax call to custom API (requests key, supplying email and pass) and as soon as key is available, makes other ajax calls to custom API with this key. e.g. update own email, phone, etc. Instead of developing custom authorization system, I'd like to use PW built-in authorization. So, my questions are: 1. How to generate key which PW uses to set cookie that is uses to identify session/logged-in user. I guess in my custom API login handler I should create new user session and return some token/key? E.g. how to do that using PW API? 2. Assumed SPA got this key and makes next ajax request to API with this key included in query - how to authorize request / identify user with help of PW API? In sum - I need some guidance on PW API authorization methods that may help me to enable user authorization and access control in custom API from SPA ajax calls.1 point
-
@adrian Als I see it know, this answer is the logic itself and it works very well. PW and its community is fantastic, thx1 point
-
I think the problem is that you need to foreach all the instruments, not just the ones in the user's instrument field. Probably something like this: foreach ($pages->get("/instruments/")->children() as $instr){ $person = $users->find('instrument='.$instr);1 point
-
Hi, try this. $person = $users->find('instrument=' . $instr); or $person = $users->find("instrument=$instr"); // or $person = $users->find("instrument={$instr}"); Variables inside single quote is just text / string. With double quotes php parses variables.1 point
-
$person = $users->find("instrument=$instr"); or: $person = $users->find('instrument='.$instr); Variables won't be parsed inside single quotes!1 point
-
Try the develop branch of this module - it looks like it has been fixed there: https://github.com/justonestep/processwire-imageextra/blob/develop/ImageExtra.module#L1081 point
-
Thanks. Currently working on some pending fixes, but I'll take a closer look at these soon1 point
-
Do you have ajax loading enabled? It might be the case, that the javascript required is not supporting ajax loaded fields.1 point
-
Looks fine, though perhaps you can add an error checking too (not only success). I would perhaps use httpUrl() instead the relative url, especially for the js location.href - some browsers may choke on that.1 point
-
This should've already been the case, but in certain situations things weren't working as expected. The icons were displayed if there was at least one row of data in the database for that page and field combination, and a bug in building the base dataset often resulted in *all* fields for enabled templates (and not just the enabled ones) having that one row of data. I pushed a fix for the config issue a while ago and I've just pushed another fix that skips non-enabled fields even if there is data for them. Still need to make some updates to the automatic data (re)generation part, but for now things should appear normal1 point
-
@szabesz That was a bug, thanks. Grab v048 to fix. @bernhard I couldn't duplicate these issues. Try reinstalling the module (make sure to backup your settings for PageThumbs first). Perhaps clearing compiled files would also help (bottom at Modules page). There's a whole lot of check to ensure there's an image to show but of course it may fail somewhere. I tried all combinations at Detais -> Formatted value for image field settings but still wasn't able to show the error. For the field appearance issue, try hard reload to get rid of cache.1 point
-
1 point
-
1 point
-
Thanks for the test example - I added an "exit" after your bd() call and that keeps the dumps panel active, so without investigating too much, I am guessing that there is a second ajax action that is clearing the dumps panel. So I think this is related to this: https://github.com/nette/tracy/issues/199 The Tracy guys might come up with a rework to make this possible, but in the meantime, I think I'll proceed with the idea of a "Persistent Dumps" panel as it has other/different benefits as well.1 point
-
For the modals, after line 352 of PageFrontEdit.js there is setBusy(false); Try adding this right before or after that line: t.trigger('pwreloaded'); I think that will work. But another route is that when the modal window closes a 'pw-modal-closed' is triggered, and that can be captured. That line 352 is within such an event handler, which may serve as a potential implementation example.1 point
-
1 point
-
Alex, an idea here, but I've not tried it yet. If you find it works, I can update our PageFrontEdit.js in a similar manner to trigger the events mentioned below. What's needed is an event triggered that you could monitor and then re-initialize your carousel. First you'd need to update the /wire/modules/Page/PageFrontEdit/PageFrontEdit.js file Starting at line 283, you'll see this: copy.hide(); orig.show(); Update that to this: copy.hide().trigger('pwreloaded'); orig.show().trigger('pwreloaded'); Then in your own JS, monitor the event and re-init your carousel when it occurs. Something like this: $(document).on('pwreloaded', function() { // whatever your carousel init code is, for example: $(this).find('.my-carousel').carousel(); }); Let me know if something like this provides what you are looking for?1 point
-
1 point
-
i think the modal just loads the admin page in an iframe, not via ajax. the easiest solution would be to only redirect if the process is NOT ProcessPageEdit. You will have to allow requests to that process if you want to allow those modals. you could also limit it even further by checking the GET parameters used by the url of the iframe (eg /page/edit?id=123&fields=whatsoever)1 point
-
Hi, I'd give it a go -- I'm working with the 3.n on several production sites w/o any issues. But I am using only few non-core modules, mind. The only thing to look out for is the namespace addition; this presented me with some initial blank screens, due to not having it in the config.php <?php tag.1 point
-
Thank you Lost, I really wish I could give you some useful information on how we convinced EIZO to use ProcessWire. However the truth is the choice of CMS was never a requirement and was left completely up to us. Since last year when I first discovered ProcessWire, I've actually never had trouble selling it in. Mentioning it's much simpler to use and securer than competitors, that more is possible with the flexibility of ProcessWire than what is with other CMS, always helps. I've actually had one site which I converted from CraftCMS to ProcessWire due to the speed in which ProcessWire runs with ProCache. Really, ProcessWire sells itself.1 point
-
Just to be safe: which version of PW? I assume PW 3+ or 2.8+ But regardless of that, you need to install this: http://modules.processwire.com/modules/image-animated-gif/ EDIT: For the record: We want to implement an equivalent of the above module into the PW 3+ / 2.8+ core. But I first need to modify / write it.1 point
-
WHOA! I'm trying to figure out what all this does #BashNewb1 point
-
Then start with catching the submit event wth Js, and start the Ajax call manually. But I guess you are already there.1 point
-
Thanks! Would it be possible to show the version control icon only for fields that are actually enabled? Now they appear on all fields and that seems a bit misleading to me (why's there the icon if it does nothing?).1 point
-
Sure, it's a gfx only design clone to demonstrate @clsource's Wire Render Pattern:1 point
-
@hellomoto, I took a quick look at your code and there are some issues there, but first things first: I'd like to suggest not going this route at all. This module is intended for change tracking, not collecting data for all page views. I can see at least three problems you will eventually run into here: the amount of data can turn your site unusable (the module is not optimized for this), this module is most likely too simplified for collecting any actually useful statistics, and finally this will slow your site down and make it difficult to cache, since each page load needs to be processed programmatically and results in a database write operation. You would be much better off with a real analytics software, such as Google Analytics – which is free and provides all the features you will ever need in terms of page views. If you're looking to avoid turning your data to Google, I'd suggest taking a closer look at Piwik, which is a free option. Now on to the code issues if you still really want to make this thing work. First of all, you're forcing $operation to be "view" by this row: if ($operation = "viewed" /*&& $page->template->name == "vessel"*/) { What you probably meant to use there was "==" instead of "=". Another issue is related to the row attaching the "viewed" hook: $this->pages->addHook('viewed', $this, 'logPageEvent'); There's no "viewed" method to hook into, so what you're looking for is either Page::render or ProcessPageView::execute: first one occurs when a page is being rendered (via API or web interface), second one when a page is being requested online. Again, I'd like to stress out that in my opinion this addition is not a good idea. Consider yourself warned1 point
-
Changed it completely, now it implements a little bit css with a hook inside InputfieldForm::render which does the magic of hiding and showing fields depending on language checkboxes. Since it's only a visual thing I removed the older hook where the languages get unpublished depending on the checkboxes. It just creates more bugs when playing around with the languages itself because the languages are a widespread feature in ProcessWire which are affecting other classes. With the new hook I am preventing that in some way since I have more control over what I am doing. public function init() { $this->addHookAfter('InputfieldForm::render', $this, 'renderForm'); } public function renderForm(HookEvent $event) { $id = $event->object->attr("id"); if($id != "ProcessPageEdit") return; $pageID = (int) $this->input->get->id; if(!$pageID) return; $page = $this->pages->get($pageID); $_out = ""; $index = ""; if($page->id){ foreach($this->languages as $key => $language) { if(!$page->languages_active->has($language)){ $_out .= "div[data-language='{$language->id}']{ display: none!important; }\n"; if($language->isDefault()){ $_out .= ".langTabs > ul li:first-child{ display: none!important; }\n"; } else { $_out .= "li[aria-controls$='__{$language->id}']{ display: none!important; }\n"; } } else { if(!$index) $index = $key; } } if($index) { $tabJSConfig = $this->wire('config')->js('LanguageTabs'); $tabJSConfig['activeTab'] = $index; $this->wire('config')->js('LanguageTabs', $tabJSConfig); } } if($_out) $_out = "<style>$_out</style>"; $event->return .= $_out; } Example: The above selection creates this inline CSS: <style> div[data-language='1029']{ display: none!important; } li[aria-controls$='__1029']{ display: none!important; } div[data-language='4286']{ display: none!important; } li[aria-controls$='__4286']{ display: none!important; } div[data-language='5842']{ display: none!important; } li[aria-controls$='__5842']{ display: none!important; } </style>1 point
-
1 point
-
I can definitely see the need for just being able to show the time picker. I have a custom inputfield for entering lists of hours that does this. The JS in the module customizes the picker to only show date — even though it's using the core datetimepicker.js $(document).on("focus", ".InputfieldHours .datepicker", function() { $(this).timepicker({ timeFormat: 'h:mm tt', ampm: true }); }); bah! Just noticed some alignment issues on my time picker in safari. :/1 point